Loading drivers/spi/spi-omap-100k.c +78 −198 Original line number Original line Diff line number Diff line Loading @@ -83,11 +83,6 @@ #define SPI_SHUTDOWN 1 #define SPI_SHUTDOWN 1 struct omap1_spi100k { struct omap1_spi100k { struct work_struct work; /* lock protects queue and registers */ spinlock_t lock; struct list_head msg_queue; struct spi_master *master; struct spi_master *master; struct clk *ick; struct clk *ick; struct clk *fck; struct clk *fck; Loading @@ -104,8 +99,6 @@ struct omap1_spi100k_cs { int word_len; int word_len; }; }; static struct workqueue_struct *omap1_spi100k_wq; #define MOD_REG_BIT(val, mask, set) do { \ #define MOD_REG_BIT(val, mask, set) do { \ if (set) \ if (set) \ val |= mask; \ val |= mask; \ Loading Loading @@ -310,50 +303,36 @@ static int omap1_spi100k_setup(struct spi_device *spi) spi100k_open(spi->master); spi100k_open(spi->master); clk_enable(spi100k->ick); clk_prepare_enable(spi100k->ick); clk_enable(spi100k->fck); clk_prepare_enable(spi100k->fck); ret = omap1_spi100k_setup_transfer(spi, NULL); ret = omap1_spi100k_setup_transfer(spi, NULL); clk_disable(spi100k->ick); clk_disable_unprepare(spi100k->ick); clk_disable(spi100k->fck); clk_disable_unprepare(spi100k->fck); return ret; return ret; } } static void omap1_spi100k_work(struct work_struct *work) static int omap1_spi100k_prepare_hardware(struct spi_master *master) { { struct omap1_spi100k *spi100k; struct omap1_spi100k *spi100k = spi_master_get_devdata(master); int status = 0; spi100k = container_of(work, struct omap1_spi100k, work); clk_prepare_enable(spi100k->ick); spin_lock_irq(&spi100k->lock); clk_prepare_enable(spi100k->fck); clk_enable(spi100k->ick); return 0; clk_enable(spi100k->fck); } /* We only enable one channel at a time -- the one whose message is static int omap1_spi100k_transfer_one_message(struct spi_master *master, * at the head of the queue -- although this controller would gladly struct spi_message *m) * arbitrate among multiple channels. This corresponds to "single { * channel" master mode. As a side effect, we need to manage the struct omap1_spi100k *spi100k = spi_master_get_devdata(master); * chipselect with the FORCE bit ... CS != channel enable. struct spi_device *spi = m->spi; */ while (!list_empty(&spi100k->msg_queue)) { struct spi_message *m; struct spi_device *spi; struct spi_transfer *t = NULL; struct spi_transfer *t = NULL; int cs_active = 0; int cs_active = 0; struct omap1_spi100k_cs *cs; int par_override = 0; int par_override = 0; int status = 0; m = container_of(spi100k->msg_queue.next, struct spi_message, queue); list_del_init(&m->queue); spin_unlock_irq(&spi100k->lock); spi = m->spi; cs = spi->controller_state; list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) { if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { Loading Loading @@ -407,73 +386,19 @@ static void omap1_spi100k_work(struct work_struct *work) omap1_spi100k_force_cs(spi100k, 0); omap1_spi100k_force_cs(spi100k, 0); m->status = status; m->status = status; m->complete(m->context); spin_lock_irq(&spi100k->lock); spi_finalize_current_message(master); } clk_disable(spi100k->ick); return status; clk_disable(spi100k->fck); spin_unlock_irq(&spi100k->lock); if (status < 0) printk(KERN_WARNING "spi transfer failed with %d\n", status); } } static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) static int omap1_spi100k_unprepare_hardware(struct spi_master *master) { { struct omap1_spi100k *spi100k; struct omap1_spi100k *spi100k = spi_master_get_devdata(master); unsigned long flags; struct spi_transfer *t; m->actual_length = 0; m->status = -EINPROGRESS; spi100k = spi_master_get_devdata(spi->master); /* Don't accept new work if we're shutting down */ if (spi100k->state == SPI_SHUTDOWN) return -ESHUTDOWN; /* reject invalid messages and transfers */ if (list_empty(&m->transfers) || !m->complete) return -EINVAL; list_for_each_entry(t, &m->transfers, transfer_list) { const void *tx_buf = t->tx_buf; void *rx_buf = t->rx_buf; unsigned len = t->len; if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ || (len && !(rx_buf || tx_buf))) { dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", t->speed_hz, len, tx_buf ? "tx" : "", rx_buf ? "rx" : "", t->bits_per_word); return -EINVAL; } if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) { dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", t->speed_hz, OMAP1_SPI100K_MAX_FREQ/(1<<16)); return -EINVAL; } } spin_lock_irqsave(&spi100k->lock, flags); list_add_tail(&m->queue, &spi100k->msg_queue); queue_work(omap1_spi100k_wq, &spi100k->work); spin_unlock_irqrestore(&spi100k->lock, flags); return 0; clk_disable_unprepare(spi100k->ick); } clk_disable_unprepare(spi100k->fck); static int omap1_spi100k_reset(struct omap1_spi100k *spi100k) { return 0; return 0; } } Loading @@ -496,11 +421,15 @@ static int omap1_spi100k_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->bus_num = pdev->id; master->setup = omap1_spi100k_setup; master->setup = omap1_spi100k_setup; master->transfer = omap1_spi100k_transfer; master->transfer_one_message = omap1_spi100k_transfer_one_message; master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware; master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware; master->cleanup = NULL; master->cleanup = NULL; master->num_chipselect = 2; master->num_chipselect = 2; master->mode_bits = MODEBITS; master->mode_bits = MODEBITS; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16); master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ; platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master); Loading @@ -514,40 +443,29 @@ static int omap1_spi100k_probe(struct platform_device *pdev) */ */ spi100k->base = (void __iomem *) pdev->dev.platform_data; spi100k->base = (void __iomem *) pdev->dev.platform_data; INIT_WORK(&spi100k->work, omap1_spi100k_work); spi100k->ick = devm_clk_get(&pdev->dev, "ick"); spin_lock_init(&spi100k->lock); INIT_LIST_HEAD(&spi100k->msg_queue); spi100k->ick = clk_get(&pdev->dev, "ick"); if (IS_ERR(spi100k->ick)) { if (IS_ERR(spi100k->ick)) { dev_dbg(&pdev->dev, "can't get spi100k_ick\n"); dev_dbg(&pdev->dev, "can't get spi100k_ick\n"); status = PTR_ERR(spi100k->ick); status = PTR_ERR(spi100k->ick); goto err1; goto err; } } spi100k->fck = clk_get(&pdev->dev, "fck"); spi100k->fck = devm_clk_get(&pdev->dev, "fck"); if (IS_ERR(spi100k->fck)) { if (IS_ERR(spi100k->fck)) { dev_dbg(&pdev->dev, "can't get spi100k_fck\n"); dev_dbg(&pdev->dev, "can't get spi100k_fck\n"); status = PTR_ERR(spi100k->fck); status = PTR_ERR(spi100k->fck); goto err2; goto err; } } if (omap1_spi100k_reset(spi100k) < 0) goto err3; status = spi_register_master(master); status = spi_register_master(master); if (status < 0) if (status < 0) goto err3; goto err; spi100k->state = SPI_RUNNING; spi100k->state = SPI_RUNNING; return status; return status; err3: err: clk_put(spi100k->fck); err2: clk_put(spi100k->ick); err1: spi_master_put(master); spi_master_put(master); return status; return status; } } Loading @@ -557,33 +475,14 @@ static int omap1_spi100k_remove(struct platform_device *pdev) struct spi_master *master; struct spi_master *master; struct omap1_spi100k *spi100k; struct omap1_spi100k *spi100k; struct resource *r; struct resource *r; unsigned limit = 500; unsigned long flags; int status = 0; int status = 0; master = platform_get_drvdata(pdev); master = platform_get_drvdata(pdev); spi100k = spi_master_get_devdata(master); spi100k = spi_master_get_devdata(master); spin_lock_irqsave(&spi100k->lock, flags); spi100k->state = SPI_SHUTDOWN; while (!list_empty(&spi100k->msg_queue) && limit--) { spin_unlock_irqrestore(&spi100k->lock, flags); msleep(10); spin_lock_irqsave(&spi100k->lock, flags); } if (!list_empty(&spi100k->msg_queue)) status = -EBUSY; spin_unlock_irqrestore(&spi100k->lock, flags); if (status != 0) if (status != 0) return status; return status; clk_put(spi100k->fck); clk_put(spi100k->ick); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi_unregister_master(master); spi_unregister_master(master); Loading @@ -596,30 +495,11 @@ static struct platform_driver omap1_spi100k_driver = { .name = "omap1_spi100k", .name = "omap1_spi100k", .owner = THIS_MODULE, .owner = THIS_MODULE, }, }, .probe = omap1_spi100k_probe, .remove = omap1_spi100k_remove, .remove = omap1_spi100k_remove, }; }; module_platform_driver(omap1_spi100k_driver); static int __init omap1_spi100k_init(void) { omap1_spi100k_wq = create_singlethread_workqueue( omap1_spi100k_driver.driver.name); if (omap1_spi100k_wq == NULL) return -1; return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe); } static void __exit omap1_spi100k_exit(void) { platform_driver_unregister(&omap1_spi100k_driver); destroy_workqueue(omap1_spi100k_wq); } module_init(omap1_spi100k_init); module_exit(omap1_spi100k_exit); MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver"); MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver"); MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>"); MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>"); Loading Loading
drivers/spi/spi-omap-100k.c +78 −198 Original line number Original line Diff line number Diff line Loading @@ -83,11 +83,6 @@ #define SPI_SHUTDOWN 1 #define SPI_SHUTDOWN 1 struct omap1_spi100k { struct omap1_spi100k { struct work_struct work; /* lock protects queue and registers */ spinlock_t lock; struct list_head msg_queue; struct spi_master *master; struct spi_master *master; struct clk *ick; struct clk *ick; struct clk *fck; struct clk *fck; Loading @@ -104,8 +99,6 @@ struct omap1_spi100k_cs { int word_len; int word_len; }; }; static struct workqueue_struct *omap1_spi100k_wq; #define MOD_REG_BIT(val, mask, set) do { \ #define MOD_REG_BIT(val, mask, set) do { \ if (set) \ if (set) \ val |= mask; \ val |= mask; \ Loading Loading @@ -310,50 +303,36 @@ static int omap1_spi100k_setup(struct spi_device *spi) spi100k_open(spi->master); spi100k_open(spi->master); clk_enable(spi100k->ick); clk_prepare_enable(spi100k->ick); clk_enable(spi100k->fck); clk_prepare_enable(spi100k->fck); ret = omap1_spi100k_setup_transfer(spi, NULL); ret = omap1_spi100k_setup_transfer(spi, NULL); clk_disable(spi100k->ick); clk_disable_unprepare(spi100k->ick); clk_disable(spi100k->fck); clk_disable_unprepare(spi100k->fck); return ret; return ret; } } static void omap1_spi100k_work(struct work_struct *work) static int omap1_spi100k_prepare_hardware(struct spi_master *master) { { struct omap1_spi100k *spi100k; struct omap1_spi100k *spi100k = spi_master_get_devdata(master); int status = 0; spi100k = container_of(work, struct omap1_spi100k, work); clk_prepare_enable(spi100k->ick); spin_lock_irq(&spi100k->lock); clk_prepare_enable(spi100k->fck); clk_enable(spi100k->ick); return 0; clk_enable(spi100k->fck); } /* We only enable one channel at a time -- the one whose message is static int omap1_spi100k_transfer_one_message(struct spi_master *master, * at the head of the queue -- although this controller would gladly struct spi_message *m) * arbitrate among multiple channels. This corresponds to "single { * channel" master mode. As a side effect, we need to manage the struct omap1_spi100k *spi100k = spi_master_get_devdata(master); * chipselect with the FORCE bit ... CS != channel enable. struct spi_device *spi = m->spi; */ while (!list_empty(&spi100k->msg_queue)) { struct spi_message *m; struct spi_device *spi; struct spi_transfer *t = NULL; struct spi_transfer *t = NULL; int cs_active = 0; int cs_active = 0; struct omap1_spi100k_cs *cs; int par_override = 0; int par_override = 0; int status = 0; m = container_of(spi100k->msg_queue.next, struct spi_message, queue); list_del_init(&m->queue); spin_unlock_irq(&spi100k->lock); spi = m->spi; cs = spi->controller_state; list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) { if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { Loading Loading @@ -407,73 +386,19 @@ static void omap1_spi100k_work(struct work_struct *work) omap1_spi100k_force_cs(spi100k, 0); omap1_spi100k_force_cs(spi100k, 0); m->status = status; m->status = status; m->complete(m->context); spin_lock_irq(&spi100k->lock); spi_finalize_current_message(master); } clk_disable(spi100k->ick); return status; clk_disable(spi100k->fck); spin_unlock_irq(&spi100k->lock); if (status < 0) printk(KERN_WARNING "spi transfer failed with %d\n", status); } } static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) static int omap1_spi100k_unprepare_hardware(struct spi_master *master) { { struct omap1_spi100k *spi100k; struct omap1_spi100k *spi100k = spi_master_get_devdata(master); unsigned long flags; struct spi_transfer *t; m->actual_length = 0; m->status = -EINPROGRESS; spi100k = spi_master_get_devdata(spi->master); /* Don't accept new work if we're shutting down */ if (spi100k->state == SPI_SHUTDOWN) return -ESHUTDOWN; /* reject invalid messages and transfers */ if (list_empty(&m->transfers) || !m->complete) return -EINVAL; list_for_each_entry(t, &m->transfers, transfer_list) { const void *tx_buf = t->tx_buf; void *rx_buf = t->rx_buf; unsigned len = t->len; if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ || (len && !(rx_buf || tx_buf))) { dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", t->speed_hz, len, tx_buf ? "tx" : "", rx_buf ? "rx" : "", t->bits_per_word); return -EINVAL; } if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) { dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", t->speed_hz, OMAP1_SPI100K_MAX_FREQ/(1<<16)); return -EINVAL; } } spin_lock_irqsave(&spi100k->lock, flags); list_add_tail(&m->queue, &spi100k->msg_queue); queue_work(omap1_spi100k_wq, &spi100k->work); spin_unlock_irqrestore(&spi100k->lock, flags); return 0; clk_disable_unprepare(spi100k->ick); } clk_disable_unprepare(spi100k->fck); static int omap1_spi100k_reset(struct omap1_spi100k *spi100k) { return 0; return 0; } } Loading @@ -496,11 +421,15 @@ static int omap1_spi100k_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->bus_num = pdev->id; master->setup = omap1_spi100k_setup; master->setup = omap1_spi100k_setup; master->transfer = omap1_spi100k_transfer; master->transfer_one_message = omap1_spi100k_transfer_one_message; master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware; master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware; master->cleanup = NULL; master->cleanup = NULL; master->num_chipselect = 2; master->num_chipselect = 2; master->mode_bits = MODEBITS; master->mode_bits = MODEBITS; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16); master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ; platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master); Loading @@ -514,40 +443,29 @@ static int omap1_spi100k_probe(struct platform_device *pdev) */ */ spi100k->base = (void __iomem *) pdev->dev.platform_data; spi100k->base = (void __iomem *) pdev->dev.platform_data; INIT_WORK(&spi100k->work, omap1_spi100k_work); spi100k->ick = devm_clk_get(&pdev->dev, "ick"); spin_lock_init(&spi100k->lock); INIT_LIST_HEAD(&spi100k->msg_queue); spi100k->ick = clk_get(&pdev->dev, "ick"); if (IS_ERR(spi100k->ick)) { if (IS_ERR(spi100k->ick)) { dev_dbg(&pdev->dev, "can't get spi100k_ick\n"); dev_dbg(&pdev->dev, "can't get spi100k_ick\n"); status = PTR_ERR(spi100k->ick); status = PTR_ERR(spi100k->ick); goto err1; goto err; } } spi100k->fck = clk_get(&pdev->dev, "fck"); spi100k->fck = devm_clk_get(&pdev->dev, "fck"); if (IS_ERR(spi100k->fck)) { if (IS_ERR(spi100k->fck)) { dev_dbg(&pdev->dev, "can't get spi100k_fck\n"); dev_dbg(&pdev->dev, "can't get spi100k_fck\n"); status = PTR_ERR(spi100k->fck); status = PTR_ERR(spi100k->fck); goto err2; goto err; } } if (omap1_spi100k_reset(spi100k) < 0) goto err3; status = spi_register_master(master); status = spi_register_master(master); if (status < 0) if (status < 0) goto err3; goto err; spi100k->state = SPI_RUNNING; spi100k->state = SPI_RUNNING; return status; return status; err3: err: clk_put(spi100k->fck); err2: clk_put(spi100k->ick); err1: spi_master_put(master); spi_master_put(master); return status; return status; } } Loading @@ -557,33 +475,14 @@ static int omap1_spi100k_remove(struct platform_device *pdev) struct spi_master *master; struct spi_master *master; struct omap1_spi100k *spi100k; struct omap1_spi100k *spi100k; struct resource *r; struct resource *r; unsigned limit = 500; unsigned long flags; int status = 0; int status = 0; master = platform_get_drvdata(pdev); master = platform_get_drvdata(pdev); spi100k = spi_master_get_devdata(master); spi100k = spi_master_get_devdata(master); spin_lock_irqsave(&spi100k->lock, flags); spi100k->state = SPI_SHUTDOWN; while (!list_empty(&spi100k->msg_queue) && limit--) { spin_unlock_irqrestore(&spi100k->lock, flags); msleep(10); spin_lock_irqsave(&spi100k->lock, flags); } if (!list_empty(&spi100k->msg_queue)) status = -EBUSY; spin_unlock_irqrestore(&spi100k->lock, flags); if (status != 0) if (status != 0) return status; return status; clk_put(spi100k->fck); clk_put(spi100k->ick); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi_unregister_master(master); spi_unregister_master(master); Loading @@ -596,30 +495,11 @@ static struct platform_driver omap1_spi100k_driver = { .name = "omap1_spi100k", .name = "omap1_spi100k", .owner = THIS_MODULE, .owner = THIS_MODULE, }, }, .probe = omap1_spi100k_probe, .remove = omap1_spi100k_remove, .remove = omap1_spi100k_remove, }; }; module_platform_driver(omap1_spi100k_driver); static int __init omap1_spi100k_init(void) { omap1_spi100k_wq = create_singlethread_workqueue( omap1_spi100k_driver.driver.name); if (omap1_spi100k_wq == NULL) return -1; return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe); } static void __exit omap1_spi100k_exit(void) { platform_driver_unregister(&omap1_spi100k_driver); destroy_workqueue(omap1_spi100k_wq); } module_init(omap1_spi100k_init); module_exit(omap1_spi100k_exit); MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver"); MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver"); MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>"); MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>"); Loading