in lpc18xx_eeprom.c [162:250]
static int lpc18xx_eeprom_probe(struct platform_device *pdev)
{
struct lpc18xx_eeprom_dev *eeprom;
struct device *dev = &pdev->dev;
struct reset_control *rst;
unsigned long clk_rate;
struct resource *res;
int ret;
eeprom = devm_kzalloc(dev, sizeof(*eeprom), GFP_KERNEL);
if (!eeprom)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg");
eeprom->reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(eeprom->reg_base))
return PTR_ERR(eeprom->reg_base);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
eeprom->mem_base = devm_ioremap_resource(dev, res);
if (IS_ERR(eeprom->mem_base))
return PTR_ERR(eeprom->mem_base);
eeprom->clk = devm_clk_get(&pdev->dev, "eeprom");
if (IS_ERR(eeprom->clk)) {
dev_err(&pdev->dev, "failed to get eeprom clock\n");
return PTR_ERR(eeprom->clk);
}
ret = clk_prepare_enable(eeprom->clk);
if (ret < 0) {
dev_err(dev, "failed to prepare/enable eeprom clk: %d\n", ret);
return ret;
}
rst = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(rst)) {
dev_err(dev, "failed to get reset: %ld\n", PTR_ERR(rst));
ret = PTR_ERR(rst);
goto err_clk;
}
ret = reset_control_assert(rst);
if (ret < 0) {
dev_err(dev, "failed to assert reset: %d\n", ret);
goto err_clk;
}
eeprom->val_bytes = 4;
eeprom->reg_bytes = 4;
/*
* Clock rate is generated by dividing the system bus clock by the
* division factor, contained in the divider register (minus 1 encoded).
*/
clk_rate = clk_get_rate(eeprom->clk);
clk_rate = DIV_ROUND_UP(clk_rate, LPC18XX_EEPROM_CLOCK_HZ) - 1;
lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_CLKDIV, clk_rate);
/*
* Writing a single word to the page will start the erase/program cycle
* automatically
*/
lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_AUTOPROG,
LPC18XX_EEPROM_AUTOPROG_WORD);
lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
LPC18XX_EEPROM_PWRDWN_YES);
eeprom->size = resource_size(res);
lpc18xx_nvmem_config.size = resource_size(res);
lpc18xx_nvmem_config.dev = dev;
lpc18xx_nvmem_config.priv = eeprom;
eeprom->nvmem = devm_nvmem_register(dev, &lpc18xx_nvmem_config);
if (IS_ERR(eeprom->nvmem)) {
ret = PTR_ERR(eeprom->nvmem);
goto err_clk;
}
platform_set_drvdata(pdev, eeprom);
return 0;
err_clk:
clk_disable_unprepare(eeprom->clk);
return ret;
}