0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/device.h>
0010 #include <linux/delay.h>
0011 #include <linux/err.h>
0012 #include <linux/io.h>
0013 #include <linux/module.h>
0014 #include <linux/mod_devicetable.h>
0015 #include <linux/nvmem-provider.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/reset.h>
0018
0019
0020 #define LPC18XX_EEPROM_AUTOPROG 0x00c
0021 #define LPC18XX_EEPROM_AUTOPROG_WORD 0x1
0022
0023 #define LPC18XX_EEPROM_CLKDIV 0x014
0024
0025 #define LPC18XX_EEPROM_PWRDWN 0x018
0026 #define LPC18XX_EEPROM_PWRDWN_NO 0x0
0027 #define LPC18XX_EEPROM_PWRDWN_YES 0x1
0028
0029 #define LPC18XX_EEPROM_INTSTAT 0xfe0
0030 #define LPC18XX_EEPROM_INTSTAT_END_OF_PROG BIT(2)
0031
0032 #define LPC18XX_EEPROM_INTSTATCLR 0xfe8
0033 #define LPC18XX_EEPROM_INTSTATCLR_PROG_CLR_ST BIT(2)
0034
0035
0036 #define LPC18XX_EEPROM_PAGE_SIZE 0x80
0037
0038
0039 #define LPC18XX_EEPROM_CLOCK_HZ 1500000
0040
0041
0042 #define LPC18XX_EEPROM_PROGRAM_TIME 3
0043
0044 struct lpc18xx_eeprom_dev {
0045 struct clk *clk;
0046 void __iomem *reg_base;
0047 void __iomem *mem_base;
0048 struct nvmem_device *nvmem;
0049 unsigned reg_bytes;
0050 unsigned val_bytes;
0051 int size;
0052 };
0053
0054 static inline void lpc18xx_eeprom_writel(struct lpc18xx_eeprom_dev *eeprom,
0055 u32 reg, u32 val)
0056 {
0057 writel(val, eeprom->reg_base + reg);
0058 }
0059
0060 static inline u32 lpc18xx_eeprom_readl(struct lpc18xx_eeprom_dev *eeprom,
0061 u32 reg)
0062 {
0063 return readl(eeprom->reg_base + reg);
0064 }
0065
0066 static int lpc18xx_eeprom_busywait_until_prog(struct lpc18xx_eeprom_dev *eeprom)
0067 {
0068 unsigned long end;
0069 u32 val;
0070
0071
0072 end = jiffies + msecs_to_jiffies(LPC18XX_EEPROM_PROGRAM_TIME * 10);
0073
0074 while (time_is_after_jiffies(end)) {
0075 val = lpc18xx_eeprom_readl(eeprom, LPC18XX_EEPROM_INTSTAT);
0076
0077 if (val & LPC18XX_EEPROM_INTSTAT_END_OF_PROG) {
0078 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_INTSTATCLR,
0079 LPC18XX_EEPROM_INTSTATCLR_PROG_CLR_ST);
0080 return 0;
0081 }
0082
0083 usleep_range(LPC18XX_EEPROM_PROGRAM_TIME * USEC_PER_MSEC,
0084 (LPC18XX_EEPROM_PROGRAM_TIME + 1) * USEC_PER_MSEC);
0085 }
0086
0087 return -ETIMEDOUT;
0088 }
0089
0090 static int lpc18xx_eeprom_gather_write(void *context, unsigned int reg,
0091 void *val, size_t bytes)
0092 {
0093 struct lpc18xx_eeprom_dev *eeprom = context;
0094 unsigned int offset = reg;
0095 int ret;
0096
0097
0098
0099
0100
0101 if ((reg > eeprom->size - LPC18XX_EEPROM_PAGE_SIZE) ||
0102 (reg + bytes > eeprom->size - LPC18XX_EEPROM_PAGE_SIZE))
0103 return -EINVAL;
0104
0105
0106 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
0107 LPC18XX_EEPROM_PWRDWN_NO);
0108
0109
0110 usleep_range(100, 200);
0111
0112 while (bytes) {
0113 writel(*(u32 *)val, eeprom->mem_base + offset);
0114 ret = lpc18xx_eeprom_busywait_until_prog(eeprom);
0115 if (ret < 0)
0116 return ret;
0117
0118 bytes -= eeprom->val_bytes;
0119 val += eeprom->val_bytes;
0120 offset += eeprom->val_bytes;
0121 }
0122
0123 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
0124 LPC18XX_EEPROM_PWRDWN_YES);
0125
0126 return 0;
0127 }
0128
0129 static int lpc18xx_eeprom_read(void *context, unsigned int offset,
0130 void *val, size_t bytes)
0131 {
0132 struct lpc18xx_eeprom_dev *eeprom = context;
0133
0134 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
0135 LPC18XX_EEPROM_PWRDWN_NO);
0136
0137
0138 usleep_range(100, 200);
0139
0140 while (bytes) {
0141 *(u32 *)val = readl(eeprom->mem_base + offset);
0142 bytes -= eeprom->val_bytes;
0143 val += eeprom->val_bytes;
0144 offset += eeprom->val_bytes;
0145 }
0146
0147 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
0148 LPC18XX_EEPROM_PWRDWN_YES);
0149
0150 return 0;
0151 }
0152
0153
0154 static struct nvmem_config lpc18xx_nvmem_config = {
0155 .name = "lpc18xx-eeprom",
0156 .stride = 4,
0157 .word_size = 4,
0158 .reg_read = lpc18xx_eeprom_read,
0159 .reg_write = lpc18xx_eeprom_gather_write,
0160 };
0161
0162 static int lpc18xx_eeprom_probe(struct platform_device *pdev)
0163 {
0164 struct lpc18xx_eeprom_dev *eeprom;
0165 struct device *dev = &pdev->dev;
0166 struct reset_control *rst;
0167 unsigned long clk_rate;
0168 struct resource *res;
0169 int ret;
0170
0171 eeprom = devm_kzalloc(dev, sizeof(*eeprom), GFP_KERNEL);
0172 if (!eeprom)
0173 return -ENOMEM;
0174
0175 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg");
0176 eeprom->reg_base = devm_ioremap_resource(dev, res);
0177 if (IS_ERR(eeprom->reg_base))
0178 return PTR_ERR(eeprom->reg_base);
0179
0180 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
0181 eeprom->mem_base = devm_ioremap_resource(dev, res);
0182 if (IS_ERR(eeprom->mem_base))
0183 return PTR_ERR(eeprom->mem_base);
0184
0185 eeprom->clk = devm_clk_get(&pdev->dev, "eeprom");
0186 if (IS_ERR(eeprom->clk)) {
0187 dev_err(&pdev->dev, "failed to get eeprom clock\n");
0188 return PTR_ERR(eeprom->clk);
0189 }
0190
0191 ret = clk_prepare_enable(eeprom->clk);
0192 if (ret < 0) {
0193 dev_err(dev, "failed to prepare/enable eeprom clk: %d\n", ret);
0194 return ret;
0195 }
0196
0197 rst = devm_reset_control_get_exclusive(dev, NULL);
0198 if (IS_ERR(rst)) {
0199 dev_err(dev, "failed to get reset: %ld\n", PTR_ERR(rst));
0200 ret = PTR_ERR(rst);
0201 goto err_clk;
0202 }
0203
0204 ret = reset_control_assert(rst);
0205 if (ret < 0) {
0206 dev_err(dev, "failed to assert reset: %d\n", ret);
0207 goto err_clk;
0208 }
0209
0210 eeprom->val_bytes = 4;
0211 eeprom->reg_bytes = 4;
0212
0213
0214
0215
0216
0217 clk_rate = clk_get_rate(eeprom->clk);
0218 clk_rate = DIV_ROUND_UP(clk_rate, LPC18XX_EEPROM_CLOCK_HZ) - 1;
0219 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_CLKDIV, clk_rate);
0220
0221
0222
0223
0224
0225 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_AUTOPROG,
0226 LPC18XX_EEPROM_AUTOPROG_WORD);
0227
0228 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
0229 LPC18XX_EEPROM_PWRDWN_YES);
0230
0231 eeprom->size = resource_size(res);
0232 lpc18xx_nvmem_config.size = resource_size(res);
0233 lpc18xx_nvmem_config.dev = dev;
0234 lpc18xx_nvmem_config.priv = eeprom;
0235
0236 eeprom->nvmem = devm_nvmem_register(dev, &lpc18xx_nvmem_config);
0237 if (IS_ERR(eeprom->nvmem)) {
0238 ret = PTR_ERR(eeprom->nvmem);
0239 goto err_clk;
0240 }
0241
0242 platform_set_drvdata(pdev, eeprom);
0243
0244 return 0;
0245
0246 err_clk:
0247 clk_disable_unprepare(eeprom->clk);
0248
0249 return ret;
0250 }
0251
0252 static int lpc18xx_eeprom_remove(struct platform_device *pdev)
0253 {
0254 struct lpc18xx_eeprom_dev *eeprom = platform_get_drvdata(pdev);
0255
0256 clk_disable_unprepare(eeprom->clk);
0257
0258 return 0;
0259 }
0260
0261 static const struct of_device_id lpc18xx_eeprom_of_match[] = {
0262 { .compatible = "nxp,lpc1857-eeprom" },
0263 { },
0264 };
0265 MODULE_DEVICE_TABLE(of, lpc18xx_eeprom_of_match);
0266
0267 static struct platform_driver lpc18xx_eeprom_driver = {
0268 .probe = lpc18xx_eeprom_probe,
0269 .remove = lpc18xx_eeprom_remove,
0270 .driver = {
0271 .name = "lpc18xx-eeprom",
0272 .of_match_table = lpc18xx_eeprom_of_match,
0273 },
0274 };
0275
0276 module_platform_driver(lpc18xx_eeprom_driver);
0277
0278 MODULE_AUTHOR("Ariel D'Alessandro <ariel@vanguardiasur.com.ar>");
0279 MODULE_DESCRIPTION("NXP LPC18xx EEPROM memory Driver");
0280 MODULE_LICENSE("GPL v2");