Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * NXP LPC18xx/LPC43xx EEPROM memory NVMEM driver
0004  *
0005  * Copyright (c) 2015 Ariel D'Alessandro <ariel@vanguardiasur.com>
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 /* Registers */
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 /* Fixed page size (bytes) */
0036 #define LPC18XX_EEPROM_PAGE_SIZE        0x80
0037 
0038 /* EEPROM device requires a ~1500 kHz clock (min 800 kHz, max 1600 kHz) */
0039 #define LPC18XX_EEPROM_CLOCK_HZ         1500000
0040 
0041 /* EEPROM requires 3 ms of erase/program time between each writing */
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     /* Wait until EEPROM program operation has finished */
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      * The last page contains the EEPROM initialization data and is not
0099      * writable.
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     /* Wait 100 us while the EEPROM wakes up */
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     /* Wait 100 us while the EEPROM wakes up */
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      * Clock rate is generated by dividing the system bus clock by the
0215      * division factor, contained in the divider register (minus 1 encoded).
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      * Writing a single word to the page will start the erase/program cycle
0223      * automatically
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");