• Home
  • Raw
  • Download

Lines Matching +full:meson6 +full:- +full:spifc

2  * Driver for Amlogic Meson SPI flash controller (SPIFC)
62 #define USER_UC_MASK ((BIT(5) - 1) << 27)
78 * @clk: input clock of the built-in baud rate generator
96 * meson_spifc_wait_ready() - wait for the current operation to terminate
97 * @spifc: the Meson SPI device
100 static int meson_spifc_wait_ready(struct meson_spifc *spifc) in meson_spifc_wait_ready() argument
106 regmap_read(spifc->regmap, REG_SLAVE, &data); in meson_spifc_wait_ready()
112 return -ETIMEDOUT; in meson_spifc_wait_ready()
116 * meson_spifc_drain_buffer() - copy data from device buffer to memory
117 * @spifc: the Meson SPI device
121 static void meson_spifc_drain_buffer(struct meson_spifc *spifc, u8 *buf, in meson_spifc_drain_buffer() argument
128 regmap_read(spifc->regmap, REG_C0 + i, &data); in meson_spifc_drain_buffer()
130 if (len - i >= 4) { in meson_spifc_drain_buffer()
134 memcpy(buf, &data, len - i); in meson_spifc_drain_buffer()
142 * meson_spifc_fill_buffer() - copy data from memory to device buffer
143 * @spifc: the Meson SPI device
147 static void meson_spifc_fill_buffer(struct meson_spifc *spifc, const u8 *buf, in meson_spifc_fill_buffer() argument
154 if (len - i >= 4) in meson_spifc_fill_buffer()
157 memcpy(&data, buf, len - i); in meson_spifc_fill_buffer()
159 regmap_write(spifc->regmap, REG_C0 + i, data); in meson_spifc_fill_buffer()
167 * meson_spifc_setup_speed() - program the clock divider
168 * @spifc: the Meson SPI device
171 static void meson_spifc_setup_speed(struct meson_spifc *spifc, u32 speed) in meson_spifc_setup_speed() argument
176 parent = clk_get_rate(spifc->clk); in meson_spifc_setup_speed()
177 n = max_t(int, parent / speed - 1, 1); in meson_spifc_setup_speed()
179 dev_dbg(spifc->dev, "parent %lu, speed %u, n %d\n", parent, in meson_spifc_setup_speed()
184 value |= (((n + 1) / 2 - 1) << CLOCK_CNT_HIGH_SHIFT) & in meson_spifc_setup_speed()
187 regmap_write(spifc->regmap, REG_CLOCK, value); in meson_spifc_setup_speed()
191 * meson_spifc_txrx() - transfer a chunk of data
192 * @spifc: the Meson SPI device
200 static int meson_spifc_txrx(struct meson_spifc *spifc, in meson_spifc_txrx() argument
208 if (xfer->tx_buf) in meson_spifc_txrx()
209 meson_spifc_fill_buffer(spifc, xfer->tx_buf + offset, len); in meson_spifc_txrx()
212 regmap_update_bits(spifc->regmap, REG_USER, USER_UC_MASK, in meson_spifc_txrx()
214 regmap_write(spifc->regmap, REG_USER1, in meson_spifc_txrx()
215 (8 * len - 1) << USER1_BN_UC_DOUT_SHIFT); in meson_spifc_txrx()
218 regmap_update_bits(spifc->regmap, REG_USER, USER_DIN_EN_MS, in meson_spifc_txrx()
223 keep_cs = xfer->cs_change; in meson_spifc_txrx()
225 keep_cs = !xfer->cs_change; in meson_spifc_txrx()
228 regmap_update_bits(spifc->regmap, REG_USER4, USER4_CS_ACT, in meson_spifc_txrx()
232 regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_TRST_DONE, 0); in meson_spifc_txrx()
234 regmap_update_bits(spifc->regmap, REG_CMD, CMD_USER, CMD_USER); in meson_spifc_txrx()
236 ret = meson_spifc_wait_ready(spifc); in meson_spifc_txrx()
238 if (!ret && xfer->rx_buf) in meson_spifc_txrx()
239 meson_spifc_drain_buffer(spifc, xfer->rx_buf + offset, len); in meson_spifc_txrx()
245 * meson_spifc_transfer_one() - perform a single transfer
255 struct meson_spifc *spifc = spi_master_get_devdata(master); in meson_spifc_transfer_one() local
258 meson_spifc_setup_speed(spifc, xfer->speed_hz); in meson_spifc_transfer_one()
260 regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB, 0); in meson_spifc_transfer_one()
262 while (done < xfer->len && !ret) { in meson_spifc_transfer_one()
263 len = min_t(int, xfer->len - done, SPIFC_BUFFER_SIZE); in meson_spifc_transfer_one()
264 ret = meson_spifc_txrx(spifc, xfer, done, len, in meson_spifc_transfer_one()
266 done + len >= xfer->len); in meson_spifc_transfer_one()
270 regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB, in meson_spifc_transfer_one()
277 * meson_spifc_hw_init() - reset and initialize the SPI controller
278 * @spifc: the Meson SPI device
280 static void meson_spifc_hw_init(struct meson_spifc *spifc) in meson_spifc_hw_init() argument
283 regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_SW_RST, in meson_spifc_hw_init()
286 regmap_update_bits(spifc->regmap, REG_USER, USER_CMP_MODE, 0); in meson_spifc_hw_init()
288 regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_OP_MODE, 0); in meson_spifc_hw_init()
294 struct meson_spifc *spifc; in meson_spifc_probe() local
300 master = spi_alloc_master(&pdev->dev, sizeof(struct meson_spifc)); in meson_spifc_probe()
302 return -ENOMEM; in meson_spifc_probe()
306 spifc = spi_master_get_devdata(master); in meson_spifc_probe()
307 spifc->dev = &pdev->dev; in meson_spifc_probe()
310 base = devm_ioremap_resource(spifc->dev, res); in meson_spifc_probe()
316 spifc->regmap = devm_regmap_init_mmio(spifc->dev, base, in meson_spifc_probe()
318 if (IS_ERR(spifc->regmap)) { in meson_spifc_probe()
319 ret = PTR_ERR(spifc->regmap); in meson_spifc_probe()
323 spifc->clk = devm_clk_get(spifc->dev, NULL); in meson_spifc_probe()
324 if (IS_ERR(spifc->clk)) { in meson_spifc_probe()
325 dev_err(spifc->dev, "missing clock\n"); in meson_spifc_probe()
326 ret = PTR_ERR(spifc->clk); in meson_spifc_probe()
330 ret = clk_prepare_enable(spifc->clk); in meson_spifc_probe()
332 dev_err(spifc->dev, "can't prepare clock\n"); in meson_spifc_probe()
336 rate = clk_get_rate(spifc->clk); in meson_spifc_probe()
338 master->num_chipselect = 1; in meson_spifc_probe()
339 master->dev.of_node = pdev->dev.of_node; in meson_spifc_probe()
340 master->bits_per_word_mask = SPI_BPW_MASK(8); in meson_spifc_probe()
341 master->auto_runtime_pm = true; in meson_spifc_probe()
342 master->transfer_one = meson_spifc_transfer_one; in meson_spifc_probe()
343 master->min_speed_hz = rate >> 6; in meson_spifc_probe()
344 master->max_speed_hz = rate >> 1; in meson_spifc_probe()
346 meson_spifc_hw_init(spifc); in meson_spifc_probe()
348 pm_runtime_set_active(spifc->dev); in meson_spifc_probe()
349 pm_runtime_enable(spifc->dev); in meson_spifc_probe()
351 ret = devm_spi_register_master(spifc->dev, master); in meson_spifc_probe()
353 dev_err(spifc->dev, "failed to register spi master\n"); in meson_spifc_probe()
359 clk_disable_unprepare(spifc->clk); in meson_spifc_probe()
368 struct meson_spifc *spifc = spi_master_get_devdata(master); in meson_spifc_remove() local
370 pm_runtime_get_sync(&pdev->dev); in meson_spifc_remove()
371 clk_disable_unprepare(spifc->clk); in meson_spifc_remove()
372 pm_runtime_disable(&pdev->dev); in meson_spifc_remove()
381 struct meson_spifc *spifc = spi_master_get_devdata(master); in meson_spifc_suspend() local
389 clk_disable_unprepare(spifc->clk); in meson_spifc_suspend()
397 struct meson_spifc *spifc = spi_master_get_devdata(master); in meson_spifc_resume() local
401 ret = clk_prepare_enable(spifc->clk); in meson_spifc_resume()
406 meson_spifc_hw_init(spifc); in meson_spifc_resume()
410 clk_disable_unprepare(spifc->clk); in meson_spifc_resume()
420 struct meson_spifc *spifc = spi_master_get_devdata(master); in meson_spifc_runtime_suspend() local
422 clk_disable_unprepare(spifc->clk); in meson_spifc_runtime_suspend()
430 struct meson_spifc *spifc = spi_master_get_devdata(master); in meson_spifc_runtime_resume() local
432 return clk_prepare_enable(spifc->clk); in meson_spifc_runtime_resume()
444 { .compatible = "amlogic,meson6-spifc", },
445 { .compatible = "amlogic,meson-gxbb-spifc", },
454 .name = "meson-spifc",
463 MODULE_DESCRIPTION("Amlogic Meson SPIFC driver");