Loading Documentation/driver-model/devres.txt +3 −0 Original line number Original line Diff line number Diff line Loading @@ -302,3 +302,6 @@ PHY SLAVE DMA ENGINE SLAVE DMA ENGINE devm_acpi_dma_controller_register() devm_acpi_dma_controller_register() SPI devm_spi_register_master() drivers/spi/Kconfig +1 −1 Original line number Original line Diff line number Diff line Loading @@ -393,7 +393,7 @@ config SPI_S3C24XX_FIQ config SPI_S3C64XX config SPI_S3C64XX tristate "Samsung S3C64XX series type SPI" tristate "Samsung S3C64XX series type SPI" depends on (ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS) depends on PLAT_SAMSUNG select S3C64XX_DMA if ARCH_S3C64XX select S3C64XX_DMA if ARCH_S3C64XX help help SPI driver for Samsung S3C64XX and newer SoCs. SPI driver for Samsung S3C64XX and newer SoCs. Loading drivers/spi/spi-s3c64xx.c +57 −49 Original line number Original line Diff line number Diff line Loading @@ -205,7 +205,6 @@ struct s3c64xx_spi_driver_data { #endif #endif struct s3c64xx_spi_port_config *port_conf; struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; unsigned int port_id; unsigned long gpios[4]; bool cs_gpio; bool cs_gpio; }; }; Loading Loading @@ -559,25 +558,18 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi) struct spi_device *spi) { { struct s3c64xx_spi_csinfo *cs; if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */ if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */ if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ /* Deselect the last toggled device */ /* Deselect the last toggled device */ cs = sdd->tgl_spi->controller_data; if (spi->cs_gpio >= 0) if (sdd->cs_gpio) gpio_set_value(spi->cs_gpio, gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); spi->mode & SPI_CS_HIGH ? 0 : 1); } } sdd->tgl_spi = NULL; sdd->tgl_spi = NULL; } } cs = spi->controller_data; if (spi->cs_gpio >= 0) if (sdd->cs_gpio) gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0); gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); /* Start the signals */ writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); } } static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, Loading Loading @@ -702,16 +694,11 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi) struct spi_device *spi) { { struct s3c64xx_spi_csinfo *cs = spi->controller_data; if (sdd->tgl_spi == spi) if (sdd->tgl_spi == spi) sdd->tgl_spi = NULL; sdd->tgl_spi = NULL; if (sdd->cs_gpio) if (spi->cs_gpio >= 0) gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); /* Quiese the signals */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); } } static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) Loading Loading @@ -927,6 +914,9 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, s3c64xx_spi_config(sdd); s3c64xx_spi_config(sdd); } } /* Slave Select */ enable_cs(sdd, spi); /* Polling method for xfers not bigger than FIFO capacity */ /* Polling method for xfers not bigger than FIFO capacity */ use_dma = 0; use_dma = 0; if (!is_polling(sdd) && if (!is_polling(sdd) && Loading @@ -942,8 +932,11 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, enable_datapath(sdd, spi, xfer, use_dma); enable_datapath(sdd, spi, xfer, use_dma); /* Slave Select */ /* Start the signals */ enable_cs(sdd, spi); writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); /* Start the signals */ writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); spin_unlock_irqrestore(&sdd->lock, flags); spin_unlock_irqrestore(&sdd->lock, flags); Loading @@ -968,6 +961,8 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, goto out; goto out; } } flush_fifo(sdd); if (xfer->delay_usecs) if (xfer->delay_usecs) udelay(xfer->delay_usecs); udelay(xfer->delay_usecs); Loading @@ -980,15 +975,17 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, } } msg->actual_length += xfer->len; msg->actual_length += xfer->len; flush_fifo(sdd); } } out: out: if (!cs_toggle || status) if (!cs_toggle || status) { /* Quiese the signals */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); disable_cs(sdd, spi); else } else { sdd->tgl_spi = spi; sdd->tgl_spi = spi; } s3c64xx_spi_unmap_mssg(sdd, msg); s3c64xx_spi_unmap_mssg(sdd, msg); Loading Loading @@ -1089,6 +1086,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) cs->line, err); cs->line, err); goto err_gpio_req; goto err_gpio_req; } } spi->cs_gpio = cs->line; } } spi_set_ctldata(spi, cs); spi_set_ctldata(spi, cs); Loading Loading @@ -1135,11 +1134,13 @@ static int s3c64xx_spi_setup(struct spi_device *spi) } } pm_runtime_put(&sdd->pdev->dev); pm_runtime_put(&sdd->pdev->dev); writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); disable_cs(sdd, spi); return 0; return 0; setup_exit: setup_exit: /* setup() returns with device de-selected */ /* setup() returns with device de-selected */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); disable_cs(sdd, spi); gpio_free(cs->line); gpio_free(cs->line); Loading @@ -1158,8 +1159,8 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi) struct s3c64xx_spi_driver_data *sdd; struct s3c64xx_spi_driver_data *sdd; sdd = spi_master_get_devdata(spi->master); sdd = spi_master_get_devdata(spi->master); if (cs && sdd->cs_gpio) { if (spi->cs_gpio) { gpio_free(cs->line); gpio_free(spi->cs_gpio); if (spi->dev.of_node) if (spi->dev.of_node) kfree(cs); kfree(cs); } } Loading Loading @@ -1448,9 +1449,11 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, sdd->regs + S3C64XX_SPI_INT_EN); sdd->regs + S3C64XX_SPI_INT_EN); if (spi_register_master(master)) { pm_runtime_enable(&pdev->dev); dev_err(&pdev->dev, "cannot register SPI master\n"); ret = -EBUSY; ret = devm_spi_register_master(&pdev->dev, master); if (ret != 0) { dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret); goto err3; goto err3; } } Loading @@ -1460,8 +1463,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) mem_res, mem_res, sdd->rx_dma.dmach, sdd->tx_dma.dmach); sdd->rx_dma.dmach, sdd->tx_dma.dmach); pm_runtime_enable(&pdev->dev); return 0; return 0; err3: err3: Loading @@ -1481,16 +1482,12 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev); spi_unregister_master(master); writel(0, sdd->regs + S3C64XX_SPI_INT_EN); writel(0, sdd->regs + S3C64XX_SPI_INT_EN); clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->clk); clk_disable_unprepare(sdd->clk); spi_master_put(master); return 0; return 0; } } Loading Loading @@ -1548,9 +1545,17 @@ static int s3c64xx_spi_runtime_resume(struct device *dev) { { struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); int ret; clk_prepare_enable(sdd->src_clk); ret = clk_prepare_enable(sdd->src_clk); clk_prepare_enable(sdd->clk); if (ret != 0) return ret; ret = clk_prepare_enable(sdd->clk); if (ret != 0) { clk_disable_unprepare(sdd->src_clk); return ret; } return 0; return 0; } } Loading Loading @@ -1636,6 +1641,18 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = { }; }; static const struct of_device_id s3c64xx_spi_dt_match[] = { static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "samsung,s3c2443-spi", .data = (void *)&s3c2443_spi_port_config, }, { .compatible = "samsung,s3c6410-spi", .data = (void *)&s3c6410_spi_port_config, }, { .compatible = "samsung,s5pc100-spi", .data = (void *)&s5pc100_spi_port_config, }, { .compatible = "samsung,s5pv210-spi", .data = (void *)&s5pv210_spi_port_config, }, { .compatible = "samsung,exynos4210-spi", { .compatible = "samsung,exynos4210-spi", .data = (void *)&exynos4_spi_port_config, .data = (void *)&exynos4_spi_port_config, }, }, Loading @@ -1653,22 +1670,13 @@ static struct platform_driver s3c64xx_spi_driver = { .pm = &s3c64xx_spi_pm, .pm = &s3c64xx_spi_pm, .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), }, }, .probe = s3c64xx_spi_probe, .remove = s3c64xx_spi_remove, .remove = s3c64xx_spi_remove, .id_table = s3c64xx_spi_driver_ids, .id_table = s3c64xx_spi_driver_ids, }; }; MODULE_ALIAS("platform:s3c64xx-spi"); MODULE_ALIAS("platform:s3c64xx-spi"); static int __init s3c64xx_spi_init(void) module_platform_driver(s3c64xx_spi_driver); { return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); } subsys_initcall(s3c64xx_spi_init); static void __exit s3c64xx_spi_exit(void) { platform_driver_unregister(&s3c64xx_spi_driver); } module_exit(s3c64xx_spi_exit); MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); Loading drivers/spi/spi.c +35 −0 Original line number Original line Diff line number Diff line Loading @@ -1370,6 +1370,41 @@ done: } } EXPORT_SYMBOL_GPL(spi_register_master); EXPORT_SYMBOL_GPL(spi_register_master); static void devm_spi_unregister(struct device *dev, void *res) { spi_unregister_master(*(struct spi_master **)res); } /** * dev_spi_register_master - register managed SPI master controller * @dev: device managing SPI master * @master: initialized master, originally from spi_alloc_master() * Context: can sleep * * Register a SPI device as with spi_register_master() which will * automatically be unregister */ int devm_spi_register_master(struct device *dev, struct spi_master *master) { struct spi_master **ptr; int ret; ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); if (!ptr) return -ENOMEM; ret = spi_register_master(master); if (ret != 0) { *ptr = master; devres_add(dev, ptr); } else { devres_free(ptr); } return ret; } EXPORT_SYMBOL_GPL(devm_spi_register_master); static int __unregister(struct device *dev, void *null) static int __unregister(struct device *dev, void *null) { { spi_unregister_device(to_spi_device(dev)); spi_unregister_device(to_spi_device(dev)); Loading include/linux/spi/spi.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -462,6 +462,8 @@ extern struct spi_master * spi_alloc_master(struct device *host, unsigned size); spi_alloc_master(struct device *host, unsigned size); extern int spi_register_master(struct spi_master *master); extern int spi_register_master(struct spi_master *master); extern int devm_spi_register_master(struct device *dev, struct spi_master *master); extern void spi_unregister_master(struct spi_master *master); extern void spi_unregister_master(struct spi_master *master); extern struct spi_master *spi_busnum_to_master(u16 busnum); extern struct spi_master *spi_busnum_to_master(u16 busnum); Loading Loading
Documentation/driver-model/devres.txt +3 −0 Original line number Original line Diff line number Diff line Loading @@ -302,3 +302,6 @@ PHY SLAVE DMA ENGINE SLAVE DMA ENGINE devm_acpi_dma_controller_register() devm_acpi_dma_controller_register() SPI devm_spi_register_master()
drivers/spi/Kconfig +1 −1 Original line number Original line Diff line number Diff line Loading @@ -393,7 +393,7 @@ config SPI_S3C24XX_FIQ config SPI_S3C64XX config SPI_S3C64XX tristate "Samsung S3C64XX series type SPI" tristate "Samsung S3C64XX series type SPI" depends on (ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS) depends on PLAT_SAMSUNG select S3C64XX_DMA if ARCH_S3C64XX select S3C64XX_DMA if ARCH_S3C64XX help help SPI driver for Samsung S3C64XX and newer SoCs. SPI driver for Samsung S3C64XX and newer SoCs. Loading
drivers/spi/spi-s3c64xx.c +57 −49 Original line number Original line Diff line number Diff line Loading @@ -205,7 +205,6 @@ struct s3c64xx_spi_driver_data { #endif #endif struct s3c64xx_spi_port_config *port_conf; struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; unsigned int port_id; unsigned long gpios[4]; bool cs_gpio; bool cs_gpio; }; }; Loading Loading @@ -559,25 +558,18 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi) struct spi_device *spi) { { struct s3c64xx_spi_csinfo *cs; if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */ if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */ if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ /* Deselect the last toggled device */ /* Deselect the last toggled device */ cs = sdd->tgl_spi->controller_data; if (spi->cs_gpio >= 0) if (sdd->cs_gpio) gpio_set_value(spi->cs_gpio, gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); spi->mode & SPI_CS_HIGH ? 0 : 1); } } sdd->tgl_spi = NULL; sdd->tgl_spi = NULL; } } cs = spi->controller_data; if (spi->cs_gpio >= 0) if (sdd->cs_gpio) gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0); gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); /* Start the signals */ writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); } } static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, Loading Loading @@ -702,16 +694,11 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi) struct spi_device *spi) { { struct s3c64xx_spi_csinfo *cs = spi->controller_data; if (sdd->tgl_spi == spi) if (sdd->tgl_spi == spi) sdd->tgl_spi = NULL; sdd->tgl_spi = NULL; if (sdd->cs_gpio) if (spi->cs_gpio >= 0) gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); /* Quiese the signals */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); } } static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) Loading Loading @@ -927,6 +914,9 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, s3c64xx_spi_config(sdd); s3c64xx_spi_config(sdd); } } /* Slave Select */ enable_cs(sdd, spi); /* Polling method for xfers not bigger than FIFO capacity */ /* Polling method for xfers not bigger than FIFO capacity */ use_dma = 0; use_dma = 0; if (!is_polling(sdd) && if (!is_polling(sdd) && Loading @@ -942,8 +932,11 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, enable_datapath(sdd, spi, xfer, use_dma); enable_datapath(sdd, spi, xfer, use_dma); /* Slave Select */ /* Start the signals */ enable_cs(sdd, spi); writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); /* Start the signals */ writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); spin_unlock_irqrestore(&sdd->lock, flags); spin_unlock_irqrestore(&sdd->lock, flags); Loading @@ -968,6 +961,8 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, goto out; goto out; } } flush_fifo(sdd); if (xfer->delay_usecs) if (xfer->delay_usecs) udelay(xfer->delay_usecs); udelay(xfer->delay_usecs); Loading @@ -980,15 +975,17 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, } } msg->actual_length += xfer->len; msg->actual_length += xfer->len; flush_fifo(sdd); } } out: out: if (!cs_toggle || status) if (!cs_toggle || status) { /* Quiese the signals */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); disable_cs(sdd, spi); else } else { sdd->tgl_spi = spi; sdd->tgl_spi = spi; } s3c64xx_spi_unmap_mssg(sdd, msg); s3c64xx_spi_unmap_mssg(sdd, msg); Loading Loading @@ -1089,6 +1086,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) cs->line, err); cs->line, err); goto err_gpio_req; goto err_gpio_req; } } spi->cs_gpio = cs->line; } } spi_set_ctldata(spi, cs); spi_set_ctldata(spi, cs); Loading Loading @@ -1135,11 +1134,13 @@ static int s3c64xx_spi_setup(struct spi_device *spi) } } pm_runtime_put(&sdd->pdev->dev); pm_runtime_put(&sdd->pdev->dev); writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); disable_cs(sdd, spi); return 0; return 0; setup_exit: setup_exit: /* setup() returns with device de-selected */ /* setup() returns with device de-selected */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); disable_cs(sdd, spi); gpio_free(cs->line); gpio_free(cs->line); Loading @@ -1158,8 +1159,8 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi) struct s3c64xx_spi_driver_data *sdd; struct s3c64xx_spi_driver_data *sdd; sdd = spi_master_get_devdata(spi->master); sdd = spi_master_get_devdata(spi->master); if (cs && sdd->cs_gpio) { if (spi->cs_gpio) { gpio_free(cs->line); gpio_free(spi->cs_gpio); if (spi->dev.of_node) if (spi->dev.of_node) kfree(cs); kfree(cs); } } Loading Loading @@ -1448,9 +1449,11 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, sdd->regs + S3C64XX_SPI_INT_EN); sdd->regs + S3C64XX_SPI_INT_EN); if (spi_register_master(master)) { pm_runtime_enable(&pdev->dev); dev_err(&pdev->dev, "cannot register SPI master\n"); ret = -EBUSY; ret = devm_spi_register_master(&pdev->dev, master); if (ret != 0) { dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret); goto err3; goto err3; } } Loading @@ -1460,8 +1463,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) mem_res, mem_res, sdd->rx_dma.dmach, sdd->tx_dma.dmach); sdd->rx_dma.dmach, sdd->tx_dma.dmach); pm_runtime_enable(&pdev->dev); return 0; return 0; err3: err3: Loading @@ -1481,16 +1482,12 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev); spi_unregister_master(master); writel(0, sdd->regs + S3C64XX_SPI_INT_EN); writel(0, sdd->regs + S3C64XX_SPI_INT_EN); clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->clk); clk_disable_unprepare(sdd->clk); spi_master_put(master); return 0; return 0; } } Loading Loading @@ -1548,9 +1545,17 @@ static int s3c64xx_spi_runtime_resume(struct device *dev) { { struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); int ret; clk_prepare_enable(sdd->src_clk); ret = clk_prepare_enable(sdd->src_clk); clk_prepare_enable(sdd->clk); if (ret != 0) return ret; ret = clk_prepare_enable(sdd->clk); if (ret != 0) { clk_disable_unprepare(sdd->src_clk); return ret; } return 0; return 0; } } Loading Loading @@ -1636,6 +1641,18 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = { }; }; static const struct of_device_id s3c64xx_spi_dt_match[] = { static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "samsung,s3c2443-spi", .data = (void *)&s3c2443_spi_port_config, }, { .compatible = "samsung,s3c6410-spi", .data = (void *)&s3c6410_spi_port_config, }, { .compatible = "samsung,s5pc100-spi", .data = (void *)&s5pc100_spi_port_config, }, { .compatible = "samsung,s5pv210-spi", .data = (void *)&s5pv210_spi_port_config, }, { .compatible = "samsung,exynos4210-spi", { .compatible = "samsung,exynos4210-spi", .data = (void *)&exynos4_spi_port_config, .data = (void *)&exynos4_spi_port_config, }, }, Loading @@ -1653,22 +1670,13 @@ static struct platform_driver s3c64xx_spi_driver = { .pm = &s3c64xx_spi_pm, .pm = &s3c64xx_spi_pm, .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), }, }, .probe = s3c64xx_spi_probe, .remove = s3c64xx_spi_remove, .remove = s3c64xx_spi_remove, .id_table = s3c64xx_spi_driver_ids, .id_table = s3c64xx_spi_driver_ids, }; }; MODULE_ALIAS("platform:s3c64xx-spi"); MODULE_ALIAS("platform:s3c64xx-spi"); static int __init s3c64xx_spi_init(void) module_platform_driver(s3c64xx_spi_driver); { return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); } subsys_initcall(s3c64xx_spi_init); static void __exit s3c64xx_spi_exit(void) { platform_driver_unregister(&s3c64xx_spi_driver); } module_exit(s3c64xx_spi_exit); MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); Loading
drivers/spi/spi.c +35 −0 Original line number Original line Diff line number Diff line Loading @@ -1370,6 +1370,41 @@ done: } } EXPORT_SYMBOL_GPL(spi_register_master); EXPORT_SYMBOL_GPL(spi_register_master); static void devm_spi_unregister(struct device *dev, void *res) { spi_unregister_master(*(struct spi_master **)res); } /** * dev_spi_register_master - register managed SPI master controller * @dev: device managing SPI master * @master: initialized master, originally from spi_alloc_master() * Context: can sleep * * Register a SPI device as with spi_register_master() which will * automatically be unregister */ int devm_spi_register_master(struct device *dev, struct spi_master *master) { struct spi_master **ptr; int ret; ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); if (!ptr) return -ENOMEM; ret = spi_register_master(master); if (ret != 0) { *ptr = master; devres_add(dev, ptr); } else { devres_free(ptr); } return ret; } EXPORT_SYMBOL_GPL(devm_spi_register_master); static int __unregister(struct device *dev, void *null) static int __unregister(struct device *dev, void *null) { { spi_unregister_device(to_spi_device(dev)); spi_unregister_device(to_spi_device(dev)); Loading
include/linux/spi/spi.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -462,6 +462,8 @@ extern struct spi_master * spi_alloc_master(struct device *host, unsigned size); spi_alloc_master(struct device *host, unsigned size); extern int spi_register_master(struct spi_master *master); extern int spi_register_master(struct spi_master *master); extern int devm_spi_register_master(struct device *dev, struct spi_master *master); extern void spi_unregister_master(struct spi_master *master); extern void spi_unregister_master(struct spi_master *master); extern struct spi_master *spi_busnum_to_master(u16 busnum); extern struct spi_master *spi_busnum_to_master(u16 busnum); Loading