Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // Driver for Amlogic Meson SPI flash controller (SPIFC)
0004 //
0005 // Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
0006 //
0007 
0008 #include <linux/clk.h>
0009 #include <linux/delay.h>
0010 #include <linux/device.h>
0011 #include <linux/io.h>
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/pm_runtime.h>
0017 #include <linux/regmap.h>
0018 #include <linux/spi/spi.h>
0019 #include <linux/types.h>
0020 
0021 /* register map */
0022 #define REG_CMD         0x00
0023 #define REG_ADDR        0x04
0024 #define REG_CTRL        0x08
0025 #define REG_CTRL1       0x0c
0026 #define REG_STATUS      0x10
0027 #define REG_CTRL2       0x14
0028 #define REG_CLOCK       0x18
0029 #define REG_USER        0x1c
0030 #define REG_USER1       0x20
0031 #define REG_USER2       0x24
0032 #define REG_USER3       0x28
0033 #define REG_USER4       0x2c
0034 #define REG_SLAVE       0x30
0035 #define REG_SLAVE1      0x34
0036 #define REG_SLAVE2      0x38
0037 #define REG_SLAVE3      0x3c
0038 #define REG_C0          0x40
0039 #define REG_B8          0x60
0040 #define REG_MAX         0x7c
0041 
0042 /* register fields */
0043 #define CMD_USER        BIT(18)
0044 #define CTRL_ENABLE_AHB     BIT(17)
0045 #define CLOCK_SOURCE        BIT(31)
0046 #define CLOCK_DIV_SHIFT     12
0047 #define CLOCK_DIV_MASK      (0x3f << CLOCK_DIV_SHIFT)
0048 #define CLOCK_CNT_HIGH_SHIFT    6
0049 #define CLOCK_CNT_HIGH_MASK (0x3f << CLOCK_CNT_HIGH_SHIFT)
0050 #define CLOCK_CNT_LOW_SHIFT 0
0051 #define CLOCK_CNT_LOW_MASK  (0x3f << CLOCK_CNT_LOW_SHIFT)
0052 #define USER_DIN_EN_MS      BIT(0)
0053 #define USER_CMP_MODE       BIT(2)
0054 #define USER_UC_DOUT_SEL    BIT(27)
0055 #define USER_UC_DIN_SEL     BIT(28)
0056 #define USER_UC_MASK        ((BIT(5) - 1) << 27)
0057 #define USER1_BN_UC_DOUT_SHIFT  17
0058 #define USER1_BN_UC_DOUT_MASK   (0xff << 16)
0059 #define USER1_BN_UC_DIN_SHIFT   8
0060 #define USER1_BN_UC_DIN_MASK    (0xff << 8)
0061 #define USER4_CS_ACT        BIT(30)
0062 #define SLAVE_TRST_DONE     BIT(4)
0063 #define SLAVE_OP_MODE       BIT(30)
0064 #define SLAVE_SW_RST        BIT(31)
0065 
0066 #define SPIFC_BUFFER_SIZE   64
0067 
0068 /**
0069  * struct meson_spifc
0070  * @master: the SPI master
0071  * @regmap: regmap for device registers
0072  * @clk:    input clock of the built-in baud rate generator
0073  * @dev:    the device structure
0074  */
0075 struct meson_spifc {
0076     struct spi_master *master;
0077     struct regmap *regmap;
0078     struct clk *clk;
0079     struct device *dev;
0080 };
0081 
0082 static const struct regmap_config spifc_regmap_config = {
0083     .reg_bits = 32,
0084     .val_bits = 32,
0085     .reg_stride = 4,
0086     .max_register = REG_MAX,
0087 };
0088 
0089 /**
0090  * meson_spifc_wait_ready() - wait for the current operation to terminate
0091  * @spifc:  the Meson SPI device
0092  * Return:  0 on success, a negative value on error
0093  */
0094 static int meson_spifc_wait_ready(struct meson_spifc *spifc)
0095 {
0096     unsigned long deadline = jiffies + msecs_to_jiffies(5);
0097     u32 data;
0098 
0099     do {
0100         regmap_read(spifc->regmap, REG_SLAVE, &data);
0101         if (data & SLAVE_TRST_DONE)
0102             return 0;
0103         cond_resched();
0104     } while (!time_after(jiffies, deadline));
0105 
0106     return -ETIMEDOUT;
0107 }
0108 
0109 /**
0110  * meson_spifc_drain_buffer() - copy data from device buffer to memory
0111  * @spifc:  the Meson SPI device
0112  * @buf:    the destination buffer
0113  * @len:    number of bytes to copy
0114  */
0115 static void meson_spifc_drain_buffer(struct meson_spifc *spifc, u8 *buf,
0116                      int len)
0117 {
0118     u32 data;
0119     int i = 0;
0120 
0121     while (i < len) {
0122         regmap_read(spifc->regmap, REG_C0 + i, &data);
0123 
0124         if (len - i >= 4) {
0125             *((u32 *)buf) = data;
0126             buf += 4;
0127         } else {
0128             memcpy(buf, &data, len - i);
0129             break;
0130         }
0131         i += 4;
0132     }
0133 }
0134 
0135 /**
0136  * meson_spifc_fill_buffer() - copy data from memory to device buffer
0137  * @spifc:  the Meson SPI device
0138  * @buf:    the source buffer
0139  * @len:    number of bytes to copy
0140  */
0141 static void meson_spifc_fill_buffer(struct meson_spifc *spifc, const u8 *buf,
0142                     int len)
0143 {
0144     u32 data;
0145     int i = 0;
0146 
0147     while (i < len) {
0148         if (len - i >= 4)
0149             data = *(u32 *)buf;
0150         else
0151             memcpy(&data, buf, len - i);
0152 
0153         regmap_write(spifc->regmap, REG_C0 + i, data);
0154 
0155         buf += 4;
0156         i += 4;
0157     }
0158 }
0159 
0160 /**
0161  * meson_spifc_setup_speed() - program the clock divider
0162  * @spifc:  the Meson SPI device
0163  * @speed:  desired speed in Hz
0164  */
0165 static void meson_spifc_setup_speed(struct meson_spifc *spifc, u32 speed)
0166 {
0167     unsigned long parent, value;
0168     int n;
0169 
0170     parent = clk_get_rate(spifc->clk);
0171     n = max_t(int, parent / speed - 1, 1);
0172 
0173     dev_dbg(spifc->dev, "parent %lu, speed %u, n %d\n", parent,
0174         speed, n);
0175 
0176     value = (n << CLOCK_DIV_SHIFT) & CLOCK_DIV_MASK;
0177     value |= (n << CLOCK_CNT_LOW_SHIFT) & CLOCK_CNT_LOW_MASK;
0178     value |= (((n + 1) / 2 - 1) << CLOCK_CNT_HIGH_SHIFT) &
0179         CLOCK_CNT_HIGH_MASK;
0180 
0181     regmap_write(spifc->regmap, REG_CLOCK, value);
0182 }
0183 
0184 /**
0185  * meson_spifc_txrx() - transfer a chunk of data
0186  * @spifc:  the Meson SPI device
0187  * @xfer:   the current SPI transfer
0188  * @offset: offset of the data to transfer
0189  * @len:    length of the data to transfer
0190  * @last_xfer:  whether this is the last transfer of the message
0191  * @last_chunk: whether this is the last chunk of the transfer
0192  * Return:  0 on success, a negative value on error
0193  */
0194 static int meson_spifc_txrx(struct meson_spifc *spifc,
0195                 struct spi_transfer *xfer,
0196                 int offset, int len, bool last_xfer,
0197                 bool last_chunk)
0198 {
0199     bool keep_cs = true;
0200     int ret;
0201 
0202     if (xfer->tx_buf)
0203         meson_spifc_fill_buffer(spifc, xfer->tx_buf + offset, len);
0204 
0205     /* enable DOUT stage */
0206     regmap_update_bits(spifc->regmap, REG_USER, USER_UC_MASK,
0207                USER_UC_DOUT_SEL);
0208     regmap_write(spifc->regmap, REG_USER1,
0209              (8 * len - 1) << USER1_BN_UC_DOUT_SHIFT);
0210 
0211     /* enable data input during DOUT */
0212     regmap_update_bits(spifc->regmap, REG_USER, USER_DIN_EN_MS,
0213                USER_DIN_EN_MS);
0214 
0215     if (last_chunk) {
0216         if (last_xfer)
0217             keep_cs = xfer->cs_change;
0218         else
0219             keep_cs = !xfer->cs_change;
0220     }
0221 
0222     regmap_update_bits(spifc->regmap, REG_USER4, USER4_CS_ACT,
0223                keep_cs ? USER4_CS_ACT : 0);
0224 
0225     /* clear transition done bit */
0226     regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_TRST_DONE, 0);
0227     /* start transfer */
0228     regmap_update_bits(spifc->regmap, REG_CMD, CMD_USER, CMD_USER);
0229 
0230     ret = meson_spifc_wait_ready(spifc);
0231 
0232     if (!ret && xfer->rx_buf)
0233         meson_spifc_drain_buffer(spifc, xfer->rx_buf + offset, len);
0234 
0235     return ret;
0236 }
0237 
0238 /**
0239  * meson_spifc_transfer_one() - perform a single transfer
0240  * @master: the SPI master
0241  * @spi:    the SPI device
0242  * @xfer:   the current SPI transfer
0243  * Return:  0 on success, a negative value on error
0244  */
0245 static int meson_spifc_transfer_one(struct spi_master *master,
0246                     struct spi_device *spi,
0247                     struct spi_transfer *xfer)
0248 {
0249     struct meson_spifc *spifc = spi_master_get_devdata(master);
0250     int len, done = 0, ret = 0;
0251 
0252     meson_spifc_setup_speed(spifc, xfer->speed_hz);
0253 
0254     regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB, 0);
0255 
0256     while (done < xfer->len && !ret) {
0257         len = min_t(int, xfer->len - done, SPIFC_BUFFER_SIZE);
0258         ret = meson_spifc_txrx(spifc, xfer, done, len,
0259                        spi_transfer_is_last(master, xfer),
0260                        done + len >= xfer->len);
0261         done += len;
0262     }
0263 
0264     regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB,
0265                CTRL_ENABLE_AHB);
0266 
0267     return ret;
0268 }
0269 
0270 /**
0271  * meson_spifc_hw_init() - reset and initialize the SPI controller
0272  * @spifc:  the Meson SPI device
0273  */
0274 static void meson_spifc_hw_init(struct meson_spifc *spifc)
0275 {
0276     /* reset device */
0277     regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_SW_RST,
0278                SLAVE_SW_RST);
0279     /* disable compatible mode */
0280     regmap_update_bits(spifc->regmap, REG_USER, USER_CMP_MODE, 0);
0281     /* set master mode */
0282     regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_OP_MODE, 0);
0283 }
0284 
0285 static int meson_spifc_probe(struct platform_device *pdev)
0286 {
0287     struct spi_master *master;
0288     struct meson_spifc *spifc;
0289     void __iomem *base;
0290     unsigned int rate;
0291     int ret = 0;
0292 
0293     master = spi_alloc_master(&pdev->dev, sizeof(struct meson_spifc));
0294     if (!master)
0295         return -ENOMEM;
0296 
0297     platform_set_drvdata(pdev, master);
0298 
0299     spifc = spi_master_get_devdata(master);
0300     spifc->dev = &pdev->dev;
0301 
0302     base = devm_platform_ioremap_resource(pdev, 0);
0303     if (IS_ERR(base)) {
0304         ret = PTR_ERR(base);
0305         goto out_err;
0306     }
0307 
0308     spifc->regmap = devm_regmap_init_mmio(spifc->dev, base,
0309                           &spifc_regmap_config);
0310     if (IS_ERR(spifc->regmap)) {
0311         ret = PTR_ERR(spifc->regmap);
0312         goto out_err;
0313     }
0314 
0315     spifc->clk = devm_clk_get(spifc->dev, NULL);
0316     if (IS_ERR(spifc->clk)) {
0317         dev_err(spifc->dev, "missing clock\n");
0318         ret = PTR_ERR(spifc->clk);
0319         goto out_err;
0320     }
0321 
0322     ret = clk_prepare_enable(spifc->clk);
0323     if (ret) {
0324         dev_err(spifc->dev, "can't prepare clock\n");
0325         goto out_err;
0326     }
0327 
0328     rate = clk_get_rate(spifc->clk);
0329 
0330     master->num_chipselect = 1;
0331     master->dev.of_node = pdev->dev.of_node;
0332     master->bits_per_word_mask = SPI_BPW_MASK(8);
0333     master->auto_runtime_pm = true;
0334     master->transfer_one = meson_spifc_transfer_one;
0335     master->min_speed_hz = rate >> 6;
0336     master->max_speed_hz = rate >> 1;
0337 
0338     meson_spifc_hw_init(spifc);
0339 
0340     pm_runtime_set_active(spifc->dev);
0341     pm_runtime_enable(spifc->dev);
0342 
0343     ret = devm_spi_register_master(spifc->dev, master);
0344     if (ret) {
0345         dev_err(spifc->dev, "failed to register spi master\n");
0346         goto out_clk;
0347     }
0348 
0349     return 0;
0350 out_clk:
0351     clk_disable_unprepare(spifc->clk);
0352     pm_runtime_disable(spifc->dev);
0353 out_err:
0354     spi_master_put(master);
0355     return ret;
0356 }
0357 
0358 static int meson_spifc_remove(struct platform_device *pdev)
0359 {
0360     struct spi_master *master = platform_get_drvdata(pdev);
0361     struct meson_spifc *spifc = spi_master_get_devdata(master);
0362 
0363     pm_runtime_get_sync(&pdev->dev);
0364     clk_disable_unprepare(spifc->clk);
0365     pm_runtime_disable(&pdev->dev);
0366 
0367     return 0;
0368 }
0369 
0370 #ifdef CONFIG_PM_SLEEP
0371 static int meson_spifc_suspend(struct device *dev)
0372 {
0373     struct spi_master *master = dev_get_drvdata(dev);
0374     struct meson_spifc *spifc = spi_master_get_devdata(master);
0375     int ret;
0376 
0377     ret = spi_master_suspend(master);
0378     if (ret)
0379         return ret;
0380 
0381     if (!pm_runtime_suspended(dev))
0382         clk_disable_unprepare(spifc->clk);
0383 
0384     return 0;
0385 }
0386 
0387 static int meson_spifc_resume(struct device *dev)
0388 {
0389     struct spi_master *master = dev_get_drvdata(dev);
0390     struct meson_spifc *spifc = spi_master_get_devdata(master);
0391     int ret;
0392 
0393     if (!pm_runtime_suspended(dev)) {
0394         ret = clk_prepare_enable(spifc->clk);
0395         if (ret)
0396             return ret;
0397     }
0398 
0399     meson_spifc_hw_init(spifc);
0400 
0401     ret = spi_master_resume(master);
0402     if (ret)
0403         clk_disable_unprepare(spifc->clk);
0404 
0405     return ret;
0406 }
0407 #endif /* CONFIG_PM_SLEEP */
0408 
0409 #ifdef CONFIG_PM
0410 static int meson_spifc_runtime_suspend(struct device *dev)
0411 {
0412     struct spi_master *master = dev_get_drvdata(dev);
0413     struct meson_spifc *spifc = spi_master_get_devdata(master);
0414 
0415     clk_disable_unprepare(spifc->clk);
0416 
0417     return 0;
0418 }
0419 
0420 static int meson_spifc_runtime_resume(struct device *dev)
0421 {
0422     struct spi_master *master = dev_get_drvdata(dev);
0423     struct meson_spifc *spifc = spi_master_get_devdata(master);
0424 
0425     return clk_prepare_enable(spifc->clk);
0426 }
0427 #endif /* CONFIG_PM */
0428 
0429 static const struct dev_pm_ops meson_spifc_pm_ops = {
0430     SET_SYSTEM_SLEEP_PM_OPS(meson_spifc_suspend, meson_spifc_resume)
0431     SET_RUNTIME_PM_OPS(meson_spifc_runtime_suspend,
0432                meson_spifc_runtime_resume,
0433                NULL)
0434 };
0435 
0436 static const struct of_device_id meson_spifc_dt_match[] = {
0437     { .compatible = "amlogic,meson6-spifc", },
0438     { .compatible = "amlogic,meson-gxbb-spifc", },
0439     { },
0440 };
0441 MODULE_DEVICE_TABLE(of, meson_spifc_dt_match);
0442 
0443 static struct platform_driver meson_spifc_driver = {
0444     .probe  = meson_spifc_probe,
0445     .remove = meson_spifc_remove,
0446     .driver = {
0447         .name       = "meson-spifc",
0448         .of_match_table = of_match_ptr(meson_spifc_dt_match),
0449         .pm     = &meson_spifc_pm_ops,
0450     },
0451 };
0452 
0453 module_platform_driver(meson_spifc_driver);
0454 
0455 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
0456 MODULE_DESCRIPTION("Amlogic Meson SPIFC driver");
0457 MODULE_LICENSE("GPL v2");