From 55e610cdd28c0ad3dce0652030c0296d549673f3 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:02 +0300 Subject: ata: sata_dwc_460ex: remove incorrect locking This lock is already taken in ata_scsi_queuecmd() a few levels up the call stack so attempting to take it here is an error. Moreover, it is pointless in the first place since it only protects a single, atomic assignment. Enabling lock debugging gives the following output: ============================================= [ INFO: possible recursive locking detected ] 4.4.0-rc5+ #189 Not tainted --------------------------------------------- kworker/u2:3/37 is trying to acquire lock: (&(&host->lock)->rlock){-.-...}, at: [<90283294>] sata_dwc_exec_command_by_tag.constprop.14+0x44/0x8c but task is already holding lock: (&(&host->lock)->rlock){-.-...}, at: [<902761ac>] ata_scsi_queuecmd+0x2c/0x330 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&(&host->lock)->rlock); lock(&(&host->lock)->rlock); *** DEADLOCK *** May be due to missing lock nesting notation 4 locks held by kworker/u2:3/37: #0: ("events_unbound"){.+.+.+}, at: [<9003a0a4>] process_one_work+0x12c/0x430 #1: ((&entry->work)){+.+.+.}, at: [<9003a0a4>] process_one_work+0x12c/0x430 #2: (&bdev->bd_mutex){+.+.+.}, at: [<9011fd54>] __blkdev_get+0x50/0x380 #3: (&(&host->lock)->rlock){-.-...}, at: [<902761ac>] ata_scsi_queuecmd+0x2c/0x330 stack backtrace: CPU: 0 PID: 37 Comm: kworker/u2:3 Not tainted 4.4.0-rc5+ #189 Workqueue: events_unbound async_run_entry_fn Stack : 90b38e30 00000021 00000003 9b2a6040 00000000 9005f3f0 904fc8dc 00000025 906b96e4 00000000 90528648 9b3336c4 904fc8dc 9009bf18 00000002 00000004 00000000 00000000 9b3336c4 9b3336e4 904fc8dc 9003d074 00000000 90500000 9005e738 00000000 00000000 00000000 00000000 00000000 00000000 00000000 6e657665 755f7374 756f626e 0000646e 00000000 00000000 9b00ca00 9b025000 ... Call Trace: [<90009d6c>] show_stack+0x88/0xa4 [<90057744>] __lock_acquire+0x1ce8/0x2154 [<900583e4>] lock_acquire+0x64/0x8c [<9045ff10>] _raw_spin_lock_irqsave+0x54/0x78 [<90283294>] sata_dwc_exec_command_by_tag.constprop.14+0x44/0x8c [<90283484>] sata_dwc_qc_issue+0x1a8/0x24c [<9026b39c>] ata_qc_issue+0x1f0/0x410 [<90273c6c>] ata_scsi_translate+0xb4/0x200 [<90276234>] ata_scsi_queuecmd+0xb4/0x330 [<9025800c>] scsi_dispatch_cmd+0xd0/0x128 [<90259934>] scsi_request_fn+0x58c/0x638 [<901a3e50>] __blk_run_queue+0x40/0x5c [<901a83d4>] blk_queue_bio+0x27c/0x28c [<901a5914>] generic_make_request+0xf0/0x188 [<901a5a54>] submit_bio+0xa8/0x194 [<9011adcc>] submit_bh_wbc.isra.23+0x15c/0x17c [<9011c908>] block_read_full_page+0x3e4/0x428 [<9009e2e0>] do_read_cache_page+0xac/0x210 [<9009fd90>] read_cache_page+0x18/0x24 [<901bbd18>] read_dev_sector+0x38/0xb0 [<901bd174>] msdos_partition+0xb4/0x5c0 [<901bcb8c>] check_partition+0x140/0x274 [<901bba60>] rescan_partitions+0xa0/0x2b0 [<9011ff68>] __blkdev_get+0x264/0x380 [<901201ac>] blkdev_get+0x128/0x36c [<901b9378>] add_disk+0x3c0/0x4bc [<90268268>] sd_probe_async+0x100/0x224 [<90043a44>] async_run_entry_fn+0x50/0x124 [<9003a11c>] process_one_work+0x1a4/0x430 [<9003a4f4>] worker_thread+0x14c/0x4fc [<900408f4>] kthread+0xd0/0xe8 [<90004338>] ret_from_kernel_thread+0x14/0x1c Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2cb6f7e..5213e22 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -924,15 +924,13 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap, struct ata_taskfile *tf, u8 tag, u32 cmd_issued) { - unsigned long flags; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command, ata_get_cmd_descript(tf->command), tag); - spin_lock_irqsave(&ap->host->lock, flags); hsdevp->cmd_issued[tag] = cmd_issued; - spin_unlock_irqrestore(&ap->host->lock, flags); + /* * Clear SError before executing a new command. * sata_dwc_scr_write and read can not be used here. Clearing the PM -- cgit v1.1 From a7e6de544c5c238a06935c96d27151432c94d2e6 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 26 Apr 2016 12:03:03 +0300 Subject: ata: sata_dwc_460ex: fix crash on offline links without an attached drive This patch fixes Machine Check "Data Write PLB Error" which happens when libata-sff's ata_sff_dev_select is trying to write into the device_addr in order to select a drive. However, SATA has no master or slave devices like the old ATA Bus, therefore selecting a different drive is kind of pointless. Data Write PLB Error Oops: Machine check, sig: 7 [#1] PowerPC 44x Platform Modules linked in: CPU: 0 PID: 508 Comm: scsi_eh_0 Not tainted 4.6.0-rc3-next-20160412+ #10 [...] NIP [c027e820] ata_sff_dev_select+0x3c/0x44 LR [c027e810] ata_sff_dev_select+0x2c/0x44 Call Trace: [cec31cd0] [c027da00] ata_sff_postreset+0x40/0xb4 (unreliable) [cec31ce0] [c027a03c] ata_eh_reset+0x5cc/0x928 [cec31d60] [c027a840] ata_eh_recover+0x330/0x10bc [cec31df0] [c027bae0] ata_do_eh+0x4c/0xa4 [...] Signed-off-by: Christian Lamparter Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 5213e22..7f95389 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1134,6 +1134,11 @@ static int sata_dwc_hardreset(struct ata_link *link, unsigned int *class, return ret; } +static void sata_dwc_dev_select(struct ata_port *ap, unsigned int device) +{ + /* SATA DWC is master only */ +} + /* * scsi mid-layer and libata interface structures */ @@ -1164,6 +1169,8 @@ static struct ata_port_operations sata_dwc_ops = { .port_start = sata_dwc_port_start, .port_stop = sata_dwc_port_stop, + .sff_dev_select = sata_dwc_dev_select, + .bmdma_setup = sata_dwc_bmdma_setup, .bmdma_start = sata_dwc_bmdma_start, }; -- cgit v1.1 From 6689dfac00ef3118f88d5b06e1f1d13899b79997 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:04 +0300 Subject: ata: sata_dwc_460ex: set dma_boundary to 0x1fff The original code states: Make sure a LLI block is not created that will span 8K max FIS boundary. If the block spans such a FIS boundary, there is a chance that a DMA burst will cross that boundary -- this results in an error in the host controller. Since we have switched to generic DMAengine API we satisfy above by setting dma_boundary value to 0x1fff. Suggested-by: Mans Rullgard Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 7f95389..aee8873 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1151,7 +1151,13 @@ static struct scsi_host_template sata_dwc_sht = { */ .sg_tablesize = LIBATA_MAX_PRD, /* .can_queue = ATA_MAX_QUEUE, */ - .dma_boundary = ATA_DMA_BOUNDARY, + /* + * Make sure a LLI block is not created that will span 8K max FIS + * boundary. If the block spans such a FIS boundary, there is a chance + * that a DMA burst will cross that boundary -- this results in an + * error in the host controller. + */ + .dma_boundary = 0x1fff /* ATA_DMA_BOUNDARY */, }; static struct ata_port_operations sata_dwc_ops = { -- cgit v1.1 From 4ea8c205e5fd1f7cac8f634347f842e12d8af9b4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:05 +0300 Subject: ata: sata_dwc_460ex: burst size must be in items not bytes The burst size as defined by DMAengine API is in items of address width. Derive burst size from AHB_DMA_BRST_DFLT (64 bytes) by dividing it to DMA_SLAVE_BUSWIDTH_4_BYTES (4 bytes) that gives us 16 items. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index aee8873..4cac27d 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -65,7 +65,7 @@ #define NO_IRQ 0 #endif -#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length*/ +#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length */ enum { SATA_DWC_MAX_PORTS = 1, @@ -318,8 +318,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd } sconf.direction = qc->dma_dir; - sconf.src_maxburst = AHB_DMA_BRST_DFLT; - sconf.dst_maxburst = AHB_DMA_BRST_DFLT; + sconf.src_maxburst = AHB_DMA_BRST_DFLT / 4; /* in items */ + sconf.dst_maxburst = AHB_DMA_BRST_DFLT / 4; /* in items */ sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -- cgit v1.1 From 59a75cef9de055e79779600f983c45580b902e6d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:06 +0300 Subject: ata: sata_dwc_460ex: DMA is always a flow controller In the original code the DMA is always a flow controller. Set this accordingly in updated code. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 4cac27d..1250e18 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -311,7 +311,7 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd if (qc->dma_dir == DMA_DEV_TO_MEM) { sconf.src_addr = addr; - sconf.device_fc = true; + sconf.device_fc = false; } else { /* DMA_MEM_TO_DEV */ sconf.dst_addr = addr; sconf.device_fc = false; -- cgit v1.1 From e1c1bee34f077baf88f78b24d08c0ba1ba506abd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:07 +0300 Subject: ata: sata_dwc_460ex: select only core part of DMA driver There is no need to have a platform driver compiled since the DMA driver is used as a library. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 5083f85..0f528d3 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -306,7 +306,7 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" depends on 460EX - select DW_DMAC + select DW_DMAC_CORE help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. -- cgit v1.1 From ae4c3485fa861af51336e066e1ba42b92af03627 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:08 +0300 Subject: ata: sata_dwc_460ex: skip dma setup for non-dma commands Calling dmaengine_prep_slave_sg() for non-dma ATA commands is unnecessary at best and could be harmful if the dma driver reacts badly to this. It also causes this driver to print a bogus error message in these cases. This patch changes sata_dwc_qc_issue() to only do the dma setup for dma commands and also reports an error to libata if if fails. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 1250e18..038e5fb 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1023,36 +1023,12 @@ static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc) sata_dwc_bmdma_start_by_tag(qc, tag); } -/* - * Function : sata_dwc_qc_prep_by_tag - * arguments : ata_queued_cmd *qc, u8 tag - * Return value : None - * qc_prep for a particular queued command based on tag - */ -static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag) -{ - struct dma_async_tx_descriptor *desc; - struct ata_port *ap = qc->ap; - struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); - - dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n", - __func__, ap->port_no, get_dma_dir_descript(qc->dma_dir), - qc->n_elem); - - desc = dma_dwc_xfer_setup(qc); - if (!desc) { - dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n", - __func__); - return; - } - hsdevp->desc[tag] = desc; -} - static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) { u32 sactive; u8 tag = qc->tag; struct ata_port *ap = qc->ap; + struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); #ifdef DEBUG_NCQ if (qc->tag > 0 || ap->link.sactive > 1) @@ -1066,7 +1042,14 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) if (!ata_is_ncq(qc->tf.protocol)) tag = 0; - sata_dwc_qc_prep_by_tag(qc, tag); + + if (ata_is_dma(qc->tf.protocol)) { + hsdevp->desc[tag] = dma_dwc_xfer_setup(qc); + if (!hsdevp->desc[tag]) + return AC_ERR_SYSTEM; + } else { + hsdevp->desc[tag] = NULL; + } if (ata_is_ncq(qc->tf.protocol)) { sactive = core_scr_read(SCR_ACTIVE); -- cgit v1.1 From 077028ecc99dc66acb3c89e33cc15c69d2edf8cb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:09 +0300 Subject: ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands ata_sff_qc_issue() can't handle DMA commands and thus we have to avoid it for them. Do call ata_bmdma_qc_issue() instead for this case. Note that the former one distinguishes PIO and DMA mode and behaves accordingly. Suggested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 038e5fb..f1a4d49 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1061,10 +1061,10 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) __func__, tag, qc->ap->link.sactive, sactive); ap->ops->sff_tf_load(ap, &qc->tf); - sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag, + sata_dwc_exec_command_by_tag(ap, &qc->tf, tag, SATA_DWC_CMD_ISSUED_PEND); } else { - ata_sff_qc_issue(qc); + return ata_bmdma_qc_issue(qc); } return 0; } -- cgit v1.1 From 50b433753df69262ed1c098328f692e882a31001 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:10 +0300 Subject: ata: sata_dwc_460ex: use "dmas" DT property to find dma channel Currently this driver only works with a DesignWare DMA engine which it registers manually using the second "reg" address range and interrupt number from the DT node. This patch makes the driver instead use the "dmas" property if present, otherwise optionally falling back on the old way so existing device trees can continue to work. With this change, there is no longer any reason to depend on the 460EX machine type so drop that from Kconfig. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/Kconfig | 11 ++- drivers/ata/sata_dwc_460ex.c | 198 ++++++++++++++++++++++++++++--------------- 2 files changed, 138 insertions(+), 71 deletions(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 0f528d3..fec5619 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -305,14 +305,21 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" - depends on 460EX - select DW_DMAC_CORE help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. If unsure, say N. +config SATA_DWC_OLD_DMA + bool "Support old device trees" + depends on SATA_DWC + select DW_DMAC_CORE + default y if 460EX + help + This option enables support for old device trees without the + "dmas" property. + config SATA_DWC_DEBUG bool "Debugging driver version" depends on SATA_DWC diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index f1a4d49..200af36 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -42,10 +43,6 @@ #include #include -/* Supported DMA engine drivers */ -#include -#include - /* These two are defined in "libata.h" */ #undef DRV_NAME #undef DRV_VERSION @@ -148,7 +145,9 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */ +#ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; +#endif }; #define SATA_DWC_QCMD_MAX 32 @@ -159,7 +158,6 @@ struct sata_dwc_device_port { int dma_pending[SATA_DWC_QCMD_MAX]; /* DMA info */ - struct dw_dma_slave *dws; struct dma_chan *chan; struct dma_async_tx_descriptor *desc[SATA_DWC_QCMD_MAX]; u32 dma_interrupt_count; @@ -198,13 +196,6 @@ struct sata_dwc_host_priv { static struct sata_dwc_host_priv host_pvt; -static struct dw_dma_slave sata_dwc_dma_dws = { - .src_id = 0, - .dst_id = 0, - .m_master = 1, - .p_master = 0, -}; - /* * Prototypes */ @@ -215,6 +206,99 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status); static void sata_dwc_port_stop(struct ata_port *ap); static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag); +#ifdef CONFIG_SATA_DWC_OLD_DMA + +#include +#include + +static struct dw_dma_slave sata_dwc_dma_dws = { + .src_id = 0, + .dst_id = 0, + .m_master = 1, + .p_master = 0, +}; + +static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param) +{ + struct dw_dma_slave *dws = &sata_dwc_dma_dws; + + if (dws->dma_dev != chan->device->dev) + return false; + + chan->private = dws; + return true; +} + +static int sata_dwc_dma_get_channel_old(struct sata_dwc_device_port *hsdevp) +{ + struct sata_dwc_device *hsdev = hsdevp->hsdev; + struct dw_dma_slave *dws = &sata_dwc_dma_dws; + dma_cap_mask_t mask; + + dws->dma_dev = hsdev->dev; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Acquire DMA channel */ + hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); + if (!hsdevp->chan) { + dev_err(hsdev->dev, "%s: dma channel unavailable\n", + __func__); + return -EAGAIN; + } + + return 0; +} + +static int sata_dwc_dma_init_old(struct platform_device *pdev, + struct sata_dwc_device *hsdev) +{ + struct device_node *np = pdev->dev.of_node; + int err; + + hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL); + if (!hsdev->dma) + return -ENOMEM; + + hsdev->dma->dev = &pdev->dev; + + /* Get SATA DMA interrupt number */ + hsdev->dma->irq = irq_of_parse_and_map(np, 1); + if (hsdev->dma->irq == NO_IRQ) { + dev_err(&pdev->dev, "no SATA DMA irq\n"); + return -ENODEV; + } + + /* Get physical SATA DMA register base address */ + hsdev->dma->regs = of_iomap(np, 1); + if (!hsdev->dma->regs) { + dev_err(&pdev->dev, + "ioremap failed for AHBDMA register address\n"); + return -ENODEV; + } + + /* Initialize AHB DMAC */ + err = dw_dma_probe(hsdev->dma); + if (err) { + iounmap(hsdev->dma->regs); + return err; + } + + return 0; +} + +static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev) +{ + if (!hsdev->dma) + return; + + dw_dma_remove(hsdev->dma); + iounmap(hsdev->dma->regs); +} + +#endif + static const char *get_prot_descript(u8 protocol) { switch ((enum ata_tf_protocols)protocol) { @@ -783,18 +867,6 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) in_le32(&hsdev->sata_dwc_regs->errmr)); } -static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param) -{ - struct sata_dwc_device_port *hsdevp = param; - struct dw_dma_slave *dws = hsdevp->dws; - - if (dws->dma_dev != chan->device->dev) - return false; - - chan->private = dws; - return true; -} - static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base) { port->cmd_addr = (void __iomem *)base + 0x00; @@ -817,6 +889,26 @@ static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base) port->ctl_addr = (void __iomem *)base + 0x20; } +static int sata_dwc_dma_get_channel(struct sata_dwc_device_port *hsdevp) +{ + struct sata_dwc_device *hsdev = hsdevp->hsdev; + struct device *dev = hsdev->dev; + +#ifdef CONFIG_SATA_DWC_OLD_DMA + if (!of_find_property(dev->of_node, "dmas", NULL)) + return sata_dwc_dma_get_channel_old(hsdevp); +#endif + + hsdevp->chan = dma_request_chan(dev, "sata-dma"); + if (IS_ERR(hsdevp->chan)) { + dev_err(dev, "failed to allocate dma channel: %ld\n", + PTR_ERR(hsdevp->chan)); + return PTR_ERR(hsdevp->chan); + } + + return 0; +} + /* * Function : sata_dwc_port_start * arguments : struct ata_ioports *port @@ -829,7 +921,6 @@ static int sata_dwc_port_start(struct ata_port *ap) struct sata_dwc_device *hsdev; struct sata_dwc_device_port *hsdevp = NULL; struct device *pdev; - dma_cap_mask_t mask; int i; hsdev = HSDEV_FROM_AP(ap); @@ -853,20 +944,9 @@ static int sata_dwc_port_start(struct ata_port *ap) } hsdevp->hsdev = hsdev; - hsdevp->dws = &sata_dwc_dma_dws; - hsdevp->dws->dma_dev = hsdev->dev; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - /* Acquire DMA channel */ - hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); - if (!hsdevp->chan) { - dev_err(hsdev->dev, "%s: dma channel unavailable\n", - __func__); - err = -EAGAIN; + err = sata_dwc_dma_get_channel(hsdevp); + if (err) goto CLEANUP_ALLOC; - } for (i = 0; i < SATA_DWC_QCMD_MAX; i++) hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; @@ -1219,33 +1299,9 @@ static int sata_dwc_probe(struct platform_device *ofdev) dev_notice(&ofdev->dev, "id %d, controller version %c.%c%c\n", idr, ver[0], ver[1], ver[2]); - /* Get SATA DMA interrupt number */ - hsdev->dma->irq = irq_of_parse_and_map(np, 1); - if (hsdev->dma->irq == NO_IRQ) { - dev_err(&ofdev->dev, "no SATA DMA irq\n"); - err = -ENODEV; - goto error_iomap; - } - - /* Get physical SATA DMA register base address */ - hsdev->dma->regs = of_iomap(np, 1); - if (!hsdev->dma->regs) { - dev_err(&ofdev->dev, - "ioremap failed for AHBDMA register address\n"); - err = -ENODEV; - goto error_iomap; - } - /* Save dev for later use in dev_xxx() routines */ hsdev->dev = &ofdev->dev; - hsdev->dma->dev = &ofdev->dev; - - /* Initialize AHB DMAC */ - err = dw_dma_probe(hsdev->dma); - if (err) - goto error_dma_iomap; - /* Enable SATA Interrupts */ sata_dwc_enable_interrupts(hsdev); @@ -1257,6 +1313,14 @@ static int sata_dwc_probe(struct platform_device *ofdev) goto error_out; } +#ifdef CONFIG_SATA_DWC_OLD_DMA + if (!of_find_property(np, "dmas", NULL)) { + err = sata_dwc_dma_init_old(ofdev, hsdev); + if (err) + goto error_out; + } +#endif + /* * Now, register with libATA core, this will also initiate the * device discovery process, invoking our port_start() handler & @@ -1270,11 +1334,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) return 0; error_out: - /* Free SATA DMA resources */ - dw_dma_remove(hsdev->dma); -error_dma_iomap: - iounmap(hsdev->dma->regs); -error_iomap: iounmap(base); return err; } @@ -1287,10 +1346,11 @@ static int sata_dwc_remove(struct platform_device *ofdev) ata_host_detach(host); +#ifdef CONFIG_SATA_DWC_OLD_DMA /* Free SATA DMA resources */ - dw_dma_remove(hsdev->dma); + sata_dwc_dma_exit_old(hsdev); +#endif - iounmap(hsdev->dma->regs); iounmap(hsdev->reg_base); dev_dbg(&ofdev->dev, "done\n"); return 0; -- cgit v1.1 From 0f48debdb90601ec37cdcb81f796ca120aae60f4 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:11 +0300 Subject: ata: sata_dwc_460ex: add phy support This adds support for powering on an optional PHY when activating the device. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/Kconfig | 1 + drivers/ata/sata_dwc_460ex.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index fec5619..3f9bbbf 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -305,6 +305,7 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" + select GENERIC_PHY help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 200af36..4b8eded 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -145,6 +146,7 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */ + struct phy *phy; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; #endif @@ -948,6 +950,10 @@ static int sata_dwc_port_start(struct ata_port *ap) if (err) goto CLEANUP_ALLOC; + err = phy_power_on(hsdev->phy); + if (err) + goto CLEANUP_ALLOC; + for (i = 0; i < SATA_DWC_QCMD_MAX; i++) hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; @@ -983,11 +989,13 @@ CLEANUP: static void sata_dwc_port_stop(struct ata_port *ap) { struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id); dmaengine_terminate_all(hsdevp->chan); dma_release_channel(hsdevp->chan); + phy_power_off(hsdev->phy); kfree(hsdevp); ap->private_data = NULL; @@ -1321,6 +1329,17 @@ static int sata_dwc_probe(struct platform_device *ofdev) } #endif + hsdev->phy = devm_phy_optional_get(hsdev->dev, "sata-phy"); + if (IS_ERR(hsdev->phy)) { + err = PTR_ERR(hsdev->phy); + hsdev->phy = NULL; + goto error_out; + } + + err = phy_init(hsdev->phy); + if (err) + goto error_out; + /* * Now, register with libATA core, this will also initiate the * device discovery process, invoking our port_start() handler & @@ -1334,6 +1353,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) return 0; error_out: + phy_exit(hsdev->phy); iounmap(base); return err; } @@ -1346,6 +1366,8 @@ static int sata_dwc_remove(struct platform_device *ofdev) ata_host_detach(host); + phy_exit(hsdev->phy); + #ifdef CONFIG_SATA_DWC_OLD_DMA /* Free SATA DMA resources */ sata_dwc_dma_exit_old(hsdev); -- cgit v1.1 From 2d20da00c324b9a4dd1c4ab9429a6376e7f4b735 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:12 +0300 Subject: ata: sata_dwc_460ex: get rid of global data This moves all global data into the driver private struct, thus permitting multiple devices of this type to be used. The core_scr_read/write() functions are replaced with equivalent calls to the existing sata_dwc_scr_read/write(). Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 79 ++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 50 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 4b8eded..24837d6 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -146,6 +146,8 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */ + u32 sactive_issued; + u32 sactive_queued; struct phy *phy; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; @@ -190,14 +192,6 @@ enum { SATA_DWC_DMA_PENDING_RX = 2, }; -struct sata_dwc_host_priv { - void __iomem *scr_addr_sstatus; - u32 sata_dwc_sactive_issued ; - u32 sata_dwc_sactive_queued ; -}; - -static struct sata_dwc_host_priv host_pvt; - /* * Prototypes */ @@ -457,21 +451,11 @@ static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) return 0; } -static u32 core_scr_read(unsigned int scr) -{ - return in_le32(host_pvt.scr_addr_sstatus + (scr * 4)); -} - -static void core_scr_write(unsigned int scr, u32 val) -{ - out_le32(host_pvt.scr_addr_sstatus + (scr * 4), val); -} - -static void clear_serror(void) +static void clear_serror(struct ata_port *ap) { u32 val; - val = core_scr_read(SCR_ERROR); - core_scr_write(SCR_ERROR, val); + sata_dwc_scr_read(&ap->link, SCR_ERROR, &val); + sata_dwc_scr_write(&ap->link, SCR_ERROR, val); } static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) @@ -498,7 +482,7 @@ static void sata_dwc_error_intr(struct ata_port *ap, ata_ehi_clear_desc(ehi); - serror = core_scr_read(SCR_ERROR); + sata_dwc_scr_read(&ap->link, SCR_ERROR, &serror); status = ap->ops->sff_check_status(ap); tag = ap->link.active_tag; @@ -509,7 +493,7 @@ static void sata_dwc_error_intr(struct ata_port *ap, hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]); /* Clear error register and interrupt bit */ - clear_serror(); + clear_serror(ap); clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR); /* This is the only error happening now. TODO check for exact error */ @@ -548,7 +532,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) int handled, num_processed, port = 0; uint intpr, sactive, sactive2, tag_mask; struct sata_dwc_device_port *hsdevp; - host_pvt.sata_dwc_sactive_issued = 0; + hsdev->sactive_issued = 0; spin_lock_irqsave(&host->lock, flags); @@ -577,7 +561,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND) dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag); - host_pvt.sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag); + hsdev->sactive_issued |= qcmd_tag_to_mask(tag); qc = ata_qc_from_tag(ap, tag); /* @@ -591,11 +575,11 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) handled = 1; goto DONE; } - sactive = core_scr_read(SCR_ACTIVE); - tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive; + sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive); + tag_mask = (hsdev->sactive_issued | sactive) ^ sactive; /* If no sactive issued and tag_mask is zero then this is not NCQ */ - if (host_pvt.sata_dwc_sactive_issued == 0 && tag_mask == 0) { + if (hsdev->sactive_issued == 0 && tag_mask == 0) { if (ap->link.active_tag == ATA_TAG_POISON) tag = 0; else @@ -665,22 +649,19 @@ DRVSTILLBUSY: */ /* process completed commands */ - sactive = core_scr_read(SCR_ACTIVE); - tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive; + sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive); + tag_mask = (hsdev->sactive_issued | sactive) ^ sactive; - if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \ - tag_mask > 1) { + if (sactive != 0 || hsdev->sactive_issued > 1 || tag_mask > 1) { dev_dbg(ap->dev, "%s NCQ:sactive=0x%08x sactive_issued=0x%08x tag_mask=0x%08x\n", - __func__, sactive, host_pvt.sata_dwc_sactive_issued, - tag_mask); + __func__, sactive, hsdev->sactive_issued, tag_mask); } - if ((tag_mask | (host_pvt.sata_dwc_sactive_issued)) != \ - (host_pvt.sata_dwc_sactive_issued)) { + if ((tag_mask | hsdev->sactive_issued) != hsdev->sactive_issued) { dev_warn(ap->dev, - "Bad tag mask? sactive=0x%08x (host_pvt.sata_dwc_sactive_issued)=0x%08x tag_mask=0x%08x\n", - sactive, host_pvt.sata_dwc_sactive_issued, tag_mask); + "Bad tag mask? sactive=0x%08x sactive_issued=0x%08x tag_mask=0x%08x\n", + sactive, hsdev->sactive_issued, tag_mask); } /* read just to clear ... not bad if currently still busy */ @@ -742,7 +723,7 @@ STILLBUSY: * we were processing --we read status as part of processing a completed * command). */ - sactive2 = core_scr_read(SCR_ACTIVE); + sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive2); if (sactive2 != sactive) { dev_dbg(ap->dev, "More completed - sactive=0x%x sactive2=0x%x\n", @@ -828,8 +809,9 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, u8 status = 0; u32 mask = 0x0; u8 tag = qc->tag; + struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); - host_pvt.sata_dwc_sactive_queued = 0; + hsdev->sactive_queued = 0; dev_dbg(ap->dev, "%s checkstatus? %x\n", __func__, check_status); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) @@ -842,10 +824,8 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, /* clear active bit */ mask = (~(qcmd_tag_to_mask(tag))); - host_pvt.sata_dwc_sactive_queued = (host_pvt.sata_dwc_sactive_queued) \ - & mask; - host_pvt.sata_dwc_sactive_issued = (host_pvt.sata_dwc_sactive_issued) \ - & mask; + hsdev->sactive_queued = hsdev->sactive_queued & mask; + hsdev->sactive_issued = hsdev->sactive_issued & mask; ata_qc_complete(qc); return 0; } @@ -974,7 +954,7 @@ static int sata_dwc_port_start(struct ata_port *ap) } /* Clear any error bits before libata starts issuing commands */ - clear_serror(); + clear_serror(ap); ap->private_data = hsdevp; dev_dbg(ap->dev, "%s: done\n", __func__); return 0; @@ -1025,7 +1005,7 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap, * managed SError register for the disk needs to be done before the * task file is loaded. */ - clear_serror(); + clear_serror(ap); ata_sff_exec_command(ap, tf); } @@ -1078,7 +1058,7 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) sata_dwc_tf_dump(ap, &qc->tf); if (start_dma) { - reg = core_scr_read(SCR_ERROR); + sata_dwc_scr_read(&ap->link, SCR_ERROR, ®); if (reg & SATA_DWC_SERROR_ERR_BITS) { dev_err(ap->dev, "%s: ****** SError=0x%08x ******\n", __func__, reg); @@ -1140,9 +1120,9 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) } if (ata_is_ncq(qc->tf.protocol)) { - sactive = core_scr_read(SCR_ACTIVE); + sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive); sactive |= (0x00000001 << tag); - core_scr_write(SCR_ACTIVE, sactive); + sata_dwc_scr_write(&ap->link, SCR_ACTIVE, sactive); dev_dbg(qc->ap->dev, "%s: tag=%d ap->link.sactive = 0x%08x sactive=0x%08x\n", @@ -1298,7 +1278,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET; - host_pvt.scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET; sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base); /* Read the ID and Version Registers */ -- cgit v1.1 From 4bb41be5eaa2788f5a5fa2047886ffeae7b0e21f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:13 +0300 Subject: ata: sata_dwc_460ex: correct HOSTDEV{P}_FROM_*() macros Here we refactor HOSTDEV{P}_FROM_*() macros to fit one line and fix the definition of HSDEV_FROM_HSDEVP() where wrong name of the parameter waas used. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 24837d6..2258baf 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -168,18 +168,13 @@ struct sata_dwc_device_port { }; /* - * Commonly used DWC SATA driver Macros + * Commonly used DWC SATA driver macros */ -#define HSDEV_FROM_HOST(host) ((struct sata_dwc_device *)\ - (host)->private_data) -#define HSDEV_FROM_AP(ap) ((struct sata_dwc_device *)\ - (ap)->host->private_data) -#define HSDEVP_FROM_AP(ap) ((struct sata_dwc_device_port *)\ - (ap)->private_data) -#define HSDEV_FROM_QC(qc) ((struct sata_dwc_device *)\ - (qc)->ap->host->private_data) -#define HSDEV_FROM_HSDEVP(p) ((struct sata_dwc_device *)\ - (hsdevp)->hsdev) +#define HSDEV_FROM_HOST(host) ((struct sata_dwc_device *)(host)->private_data) +#define HSDEV_FROM_AP(ap) ((struct sata_dwc_device *)(ap)->host->private_data) +#define HSDEVP_FROM_AP(ap) ((struct sata_dwc_device_port *)(ap)->private_data) +#define HSDEV_FROM_QC(qc) ((struct sata_dwc_device *)(qc)->ap->host->private_data) +#define HSDEV_FROM_HSDEVP(p) ((struct sata_dwc_device *)(p)->hsdev) enum { SATA_DWC_CMD_ISSUED_NOT = 0, -- cgit v1.1 From cd12ff0b5a8becd143df1f0a9dc97a4222e2cf6f Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:14 +0300 Subject: ata: sata_dwc_460ex: remove empty libata callback The sata_dwc_qc_prep() does nothing. Use the default ata_noop_qc_prep instead. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2258baf..3a9dd82 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1132,27 +1132,6 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) return 0; } -/* - * Function : sata_dwc_qc_prep - * arguments : ata_queued_cmd *qc - * Return value : None - * qc_prep for a particular queued command - */ - -static void sata_dwc_qc_prep(struct ata_queued_cmd *qc) -{ - if ((qc->dma_dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO)) - return; - -#ifdef DEBUG_NCQ - if (qc->tag > 0) - dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n", - __func__, qc->tag, qc->ap->link.active_tag); - - return ; -#endif -} - static void sata_dwc_error_handler(struct ata_port *ap) { ata_sff_error_handler(ap); @@ -1212,7 +1191,6 @@ static struct ata_port_operations sata_dwc_ops = { .error_handler = sata_dwc_error_handler, .hardreset = sata_dwc_hardreset, - .qc_prep = sata_dwc_qc_prep, .qc_issue = sata_dwc_qc_issue, .scr_read = sata_dwc_scr_read, -- cgit v1.1 From ae95d951f7cd116f663b7326422c4c759ea25b25 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:15 +0300 Subject: ata: sata_dwc_460ex: get rid of some pointless casts Casting a pointer to unsigned long only to immediately cast it back to a pointer makes no sense. Fix this. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 3a9dd82..2912e4d 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -844,26 +844,26 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) in_le32(&hsdev->sata_dwc_regs->errmr)); } -static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base) +static void sata_dwc_setup_port(struct ata_ioports *port, void __iomem *base) { - port->cmd_addr = (void __iomem *)base + 0x00; - port->data_addr = (void __iomem *)base + 0x00; + port->cmd_addr = base + 0x00; + port->data_addr = base + 0x00; - port->error_addr = (void __iomem *)base + 0x04; - port->feature_addr = (void __iomem *)base + 0x04; + port->error_addr = base + 0x04; + port->feature_addr = base + 0x04; - port->nsect_addr = (void __iomem *)base + 0x08; + port->nsect_addr = base + 0x08; - port->lbal_addr = (void __iomem *)base + 0x0c; - port->lbam_addr = (void __iomem *)base + 0x10; - port->lbah_addr = (void __iomem *)base + 0x14; + port->lbal_addr = base + 0x0c; + port->lbam_addr = base + 0x10; + port->lbah_addr = base + 0x14; - port->device_addr = (void __iomem *)base + 0x18; - port->command_addr = (void __iomem *)base + 0x1c; - port->status_addr = (void __iomem *)base + 0x1c; + port->device_addr = base + 0x18; + port->command_addr = base + 0x1c; + port->status_addr = base + 0x1c; - port->altstatus_addr = (void __iomem *)base + 0x20; - port->ctl_addr = (void __iomem *)base + 0x20; + port->altstatus_addr = base + 0x20; + port->ctl_addr = base + 0x20; } static int sata_dwc_dma_get_channel(struct sata_dwc_device_port *hsdevp) @@ -1251,7 +1251,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET; - sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base); + sata_dwc_setup_port(&host->ports[0]->ioaddr, base); /* Read the ID and Version Registers */ idr = in_le32(&hsdev->sata_dwc_regs->idr); -- cgit v1.1 From 175553ed18491bf654a64f4e1c3f8d4137ae1a56 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:16 +0300 Subject: ata: sata_dwc_460ex: get rid of incorrect cast The (void *__iomem) cast is wrong. Change the target type of the "base" pointer to void __iomem instead and drop the cast. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2912e4d..90e3e14 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1219,7 +1219,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) struct sata_dwc_device *hsdev; u32 idr, versionr; char *ver = (char *)&versionr; - u8 __iomem *base; + void __iomem *base; int err = 0; int irq; struct ata_host *host; @@ -1246,7 +1246,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); /* Synopsys DWC SATA specific Registers */ - hsdev->sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET); + hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET; /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; -- cgit v1.1 From adc64ecf8dd941e24456de9b4a02a4152ff7df15 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:17 +0300 Subject: ata: sata_dwc_460ex: add __iomem to register base pointer The pointer to the mmio register base is missing the __iomem annotation. Fix this. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 90e3e14..25e00f2 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -145,7 +145,7 @@ struct sata_dwc_device { struct ata_probe_ent *pe; /* ptr to probe-ent */ struct ata_host *host; u8 __iomem *reg_base; - struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */ + struct sata_dwc_regs __iomem *sata_dwc_regs; /* DW SATA specific */ u32 sactive_issued; u32 sactive_queued; struct phy *phy; -- cgit v1.1 From 9e8b855e9841eeb9c13e79d50f70dc000b0dfbfd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:19 +0300 Subject: ata: sata_dwc_460ex: switch to new dmaengine_terminate_* API Convert dmaengine_terminate_all() calls to synchronous and asynchronous versions where appropriate. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 25e00f2..10b6a59 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -968,7 +968,7 @@ static void sata_dwc_port_stop(struct ata_port *ap) dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id); - dmaengine_terminate_all(hsdevp->chan); + dmaengine_terminate_sync(hsdevp->chan); dma_release_channel(hsdevp->chan); phy_power_off(hsdev->phy); -- cgit v1.1 From ee81d6cc8e8aa667aabce72f39a4b806419e1d55 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:20 +0300 Subject: ata: sata_dwc_460ex: use readl/writel_relaxed() Rename the register access macros and use standard _relaxed() ops instead of __raw variants with explicit byte swapping. The original driver used the ppc-specific in/out_le32(). When it was adapted to other systems, these were added to the driver under ifdefs. However, those names are not defined as macros on ppc, so it ended up replacing them there as well with altered semantics. This patch restores the original semantics on ppc and makes the accesses no less strict on other systems. Also fixes too many sparse warnings to count. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 91 +++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 10b6a59..b7828c7 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -51,13 +51,8 @@ #define DRV_NAME "sata-dwc" #define DRV_VERSION "1.3" -#ifndef out_le32 -#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (void __iomem *)(a)) -#endif - -#ifndef in_le32 -#define in_le32(a) __le32_to_cpu(__raw_readl((void __iomem *)(a))) -#endif +#define sata_dwc_writel(a, v) writel_relaxed(v, a) +#define sata_dwc_readl(a) readl_relaxed(a) #ifndef NO_IRQ #define NO_IRQ 0 @@ -425,7 +420,7 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) return -EINVAL; } - *val = in_le32(link->ap->ioaddr.scr_addr + (scr * 4)); + *val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4)); dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", __func__, link->ap->print_id, scr, *val); @@ -441,7 +436,7 @@ static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) __func__, scr); return -EINVAL; } - out_le32(link->ap->ioaddr.scr_addr + (scr * 4), val); + sata_dwc_writel(link->ap->ioaddr.scr_addr + (scr * 4), val); return 0; } @@ -455,8 +450,8 @@ static void clear_serror(struct ata_port *ap) static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) { - out_le32(&hsdev->sata_dwc_regs->intpr, - in_le32(&hsdev->sata_dwc_regs->intpr)); + sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, + sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); } static u32 qcmd_tag_to_mask(u8 tag) @@ -532,7 +527,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) spin_lock_irqsave(&host->lock, flags); /* Read the interrupt register */ - intpr = in_le32(&hsdev->sata_dwc_regs->intpr); + intpr = sata_dwc_readl(&hsdev->sata_dwc_regs->intpr); ap = host->ports[port]; hsdevp = HSDEVP_FROM_AP(ap); @@ -551,7 +546,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) if (intpr & SATA_DWC_INTPR_NEWFP) { clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP); - tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr)); + tag = (u8)(sata_dwc_readl(&hsdev->sata_dwc_regs->fptagr)); dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag); if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND) dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag); @@ -736,13 +731,13 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) { - out_le32(&(hsdev->sata_dwc_regs->dmacr), - SATA_DWC_DMACR_RX_CLEAR( - in_le32(&(hsdev->sata_dwc_regs->dmacr)))); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_RX_CLEAR( + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); } else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) { - out_le32(&(hsdev->sata_dwc_regs->dmacr), - SATA_DWC_DMACR_TX_CLEAR( - in_le32(&(hsdev->sata_dwc_regs->dmacr)))); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_TX_CLEAR( + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); } else { /* * This should not happen, it indicates the driver is out of @@ -751,9 +746,9 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", __func__, tag, hsdevp->dma_pending[tag], - in_le32(&hsdev->sata_dwc_regs->dmacr)); - out_le32(&(hsdev->sata_dwc_regs->dmacr), - SATA_DWC_DMACR_TXRXCH_CLEAR); + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_TXRXCH_CLEAR); } } @@ -778,7 +773,7 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status) __func__, qc->tag, qc->tf.command, get_dma_dir_descript(qc->dma_dir), get_prot_descript(qc->tf.protocol), - in_le32(&(hsdev->sata_dwc_regs->dmacr))); + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)); } #endif @@ -787,7 +782,7 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status) dev_err(ap->dev, "%s DMA protocol RX and TX DMA not pending dmacr: 0x%08x\n", __func__, - in_le32(&(hsdev->sata_dwc_regs->dmacr))); + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)); } hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_NONE; @@ -828,20 +823,20 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) { /* Enable selective interrupts by setting the interrupt maskregister*/ - out_le32(&hsdev->sata_dwc_regs->intmr, - SATA_DWC_INTMR_ERRM | - SATA_DWC_INTMR_NEWFPM | - SATA_DWC_INTMR_PMABRTM | - SATA_DWC_INTMR_DMATM); + sata_dwc_writel(&hsdev->sata_dwc_regs->intmr, + SATA_DWC_INTMR_ERRM | + SATA_DWC_INTMR_NEWFPM | + SATA_DWC_INTMR_PMABRTM | + SATA_DWC_INTMR_DMATM); /* * Unmask the error bits that should trigger an error interrupt by * setting the error mask register. */ - out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS); + sata_dwc_writel(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS); dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", - __func__, in_le32(&hsdev->sata_dwc_regs->intmr), - in_le32(&hsdev->sata_dwc_regs->errmr)); + __func__, sata_dwc_readl(&hsdev->sata_dwc_regs->intmr), + sata_dwc_readl(&hsdev->sata_dwc_regs->errmr)); } static void sata_dwc_setup_port(struct ata_ioports *port, void __iomem *base) @@ -938,14 +933,14 @@ static int sata_dwc_port_start(struct ata_port *ap) if (ap->port_no == 0) { dev_dbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n", __func__); - out_le32(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_TXRXCH_CLEAR); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_TXRXCH_CLEAR); dev_dbg(ap->dev, "%s: setting burst size in DBTSR\n", __func__); - out_le32(&hsdev->sata_dwc_regs->dbtsr, - (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | - SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT))); + sata_dwc_writel(&hsdev->sata_dwc_regs->dbtsr, + (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | + SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT))); } /* Clear any error bits before libata starts issuing commands */ @@ -1060,11 +1055,11 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) } if (dir == DMA_TO_DEVICE) - out_le32(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_TXCHEN); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_TXCHEN); else - out_le32(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_RXCHEN); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_RXCHEN); /* Enable AHB DMA transfer on the specified channel */ dmaengine_submit(desc); @@ -1148,13 +1143,13 @@ static int sata_dwc_hardreset(struct ata_link *link, unsigned int *class, sata_dwc_enable_interrupts(hsdev); /* Reconfigure the DMA control register */ - out_le32(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_TXRXCH_CLEAR); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_TXRXCH_CLEAR); /* Reconfigure the DMA Burst Transaction Size register */ - out_le32(&hsdev->sata_dwc_regs->dbtsr, - SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | - SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)); + sata_dwc_writel(&hsdev->sata_dwc_regs->dbtsr, + SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | + SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)); return ret; } @@ -1254,8 +1249,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) sata_dwc_setup_port(&host->ports[0]->ioaddr, base); /* Read the ID and Version Registers */ - idr = in_le32(&hsdev->sata_dwc_regs->idr); - versionr = in_le32(&hsdev->sata_dwc_regs->versionr); + idr = sata_dwc_readl(&hsdev->sata_dwc_regs->idr); + versionr = sata_dwc_readl(&hsdev->sata_dwc_regs->versionr); dev_notice(&ofdev->dev, "id %d, controller version %c.%c%c\n", idr, ver[0], ver[1], ver[2]); -- cgit v1.1 From af50f3a8b61cfdfcf4a01b01ec2759200d362605 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 26 Apr 2016 12:03:21 +0300 Subject: ata: sata_dwc_460ex: tidy up sata_dwc_clear_dmacr() This consolidates the reads from each of the if/else branches to one place making the code a lot nicer to look at. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index b7828c7..b4459fd 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -729,15 +729,14 @@ DONE: static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) { struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp); + u32 dmacr = sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) { - sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_RX_CLEAR( - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); + dmacr = SATA_DWC_DMACR_RX_CLEAR(dmacr); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr); } else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) { - sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_TX_CLEAR( - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); + dmacr = SATA_DWC_DMACR_TX_CLEAR(dmacr); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr); } else { /* * This should not happen, it indicates the driver is out of @@ -745,8 +744,7 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) */ dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", - __func__, tag, hsdevp->dma_pending[tag], - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)); + __func__, tag, hsdevp->dma_pending[tag], dmacr); sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, SATA_DWC_DMACR_TXRXCH_CLEAR); } -- cgit v1.1 From 73ec1b5ab3a713141318ee845d8b0cc822db65b1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:22 +0300 Subject: ata: sata_dwc_460ex: use devm_ioremap This simplifies error handling and cleanup by using devm to manage IO mappings. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index b4459fd..aaff5e85 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -139,7 +139,6 @@ struct sata_dwc_device { struct device *dev; /* generic device struct */ struct ata_probe_ent *pe; /* ptr to probe-ent */ struct ata_host *host; - u8 __iomem *reg_base; struct sata_dwc_regs __iomem *sata_dwc_regs; /* DW SATA specific */ u32 sactive_issued; u32 sactive_queued; @@ -241,7 +240,7 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, struct sata_dwc_device *hsdev) { struct device_node *np = pdev->dev.of_node; - int err; + struct resource *res; hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL); if (!hsdev->dma) @@ -257,21 +256,16 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, } /* Get physical SATA DMA register base address */ - hsdev->dma->regs = of_iomap(np, 1); - if (!hsdev->dma->regs) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + hsdev->dma->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hsdev->dma->regs)) { dev_err(&pdev->dev, "ioremap failed for AHBDMA register address\n"); - return -ENODEV; + return PTR_ERR(hsdev->dma->regs); } /* Initialize AHB DMAC */ - err = dw_dma_probe(hsdev->dma); - if (err) { - iounmap(hsdev->dma->regs); - return err; - } - - return 0; + return dw_dma_probe(hsdev->dma); } static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev) @@ -280,7 +274,6 @@ static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev) return; dw_dma_remove(hsdev->dma); - iounmap(hsdev->dma->regs); } #endif @@ -1219,6 +1212,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) struct ata_port_info pi = sata_dwc_port_info[0]; const struct ata_port_info *ppi[] = { &pi, NULL }; struct device_node *np = ofdev->dev.of_node; + struct resource *res; /* Allocate DWC SATA device */ host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS); @@ -1229,13 +1223,13 @@ static int sata_dwc_probe(struct platform_device *ofdev) host->private_data = hsdev; /* Ioremap SATA registers */ - base = of_iomap(np, 0); - if (!base) { + res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&ofdev->dev, res); + if (IS_ERR(base)) { dev_err(&ofdev->dev, "ioremap failed for SATA register address\n"); - return -ENODEV; + return PTR_ERR(base); } - hsdev->reg_base = base; dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); /* Synopsys DWC SATA specific Registers */ @@ -1299,7 +1293,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) error_out: phy_exit(hsdev->phy); - iounmap(base); return err; } @@ -1318,7 +1311,6 @@ static int sata_dwc_remove(struct platform_device *ofdev) sata_dwc_dma_exit_old(hsdev); #endif - iounmap(hsdev->reg_base); dev_dbg(&ofdev->dev, "done\n"); return 0; } -- cgit v1.1 From d6ecf0c27d71666a4be46e13a1b234d17c63eb98 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:18 +0300 Subject: ata: sata_dwc_460ex: supply physical address of FIFO to DMA DMA operates with physical addresses which is not exactly the same as ioremap() returns. Introduce variable to keep physical address of the SATA FIFO register and supply it when prepare DMA channel. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index aaff5e85..6f145f8 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -95,7 +95,7 @@ struct sata_dwc_regs { u32 versionr; /* Version Register */ u32 idr; /* ID Register */ u32 unimpl[192]; /* Unimplemented */ - u32 dmadr[256]; /* FIFO Locations in DMA Mode */ + u32 dmadr[256]; /* FIFO Locations in DMA Mode */ }; enum { @@ -143,6 +143,7 @@ struct sata_dwc_device { u32 sactive_issued; u32 sactive_queued; struct phy *phy; + phys_addr_t dmadr; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; #endif @@ -368,15 +369,14 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd struct ata_port *ap = qc->ap; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); - dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr; struct dma_slave_config sconf; struct dma_async_tx_descriptor *desc; if (qc->dma_dir == DMA_DEV_TO_MEM) { - sconf.src_addr = addr; + sconf.src_addr = hsdev->dmadr; sconf.device_fc = false; } else { /* DMA_MEM_TO_DEV */ - sconf.dst_addr = addr; + sconf.dst_addr = hsdev->dmadr; sconf.device_fc = false; } @@ -399,8 +399,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd desc->callback = dma_dwc_xfer_done; desc->callback_param = hsdev; - dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n", - __func__, qc->sg, qc->n_elem, &addr); + dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pa\n", __func__, + qc->sg, qc->n_elem, &hsdev->dmadr); return desc; } @@ -1234,6 +1234,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Synopsys DWC SATA specific Registers */ hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET; + hsdev->dmadr = res->start + SATA_DWC_REG_OFFSET + offsetof(struct sata_dwc_regs, dmadr); /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; -- cgit v1.1 From bb08ab6a4c9cee6e544aeb5de3ed92cd78c6ede4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:23 +0300 Subject: ata: sata_dwc_460ex: make debug messages neat There is a duplication in the debug messages when accessing SCR registers. Remove duplication to make the messages neat. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 6f145f8..00c2af1 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -414,16 +414,16 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) } *val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4)); - dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", - __func__, link->ap->print_id, scr, *val); + dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__, + link->ap->print_id, scr, *val); return 0; } static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) { - dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", - __func__, link->ap->print_id, scr, val); + dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__, + link->ap->print_id, scr, val); if (scr > SCR_NOTIFICATION) { dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n", __func__, scr); -- cgit v1.1 From 951b8e4e673196932fa4c3b87d719644636e5ac9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Apr 2016 12:03:24 +0300 Subject: powerpc/4xx: Device tree update for the 460ex DWC SATA Device tree update for the Applied micro processor 460ex on-chip SATA to use "dmas" property. Acked-by: Rob Herring Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo --- arch/powerpc/boot/dts/canyonlands.dts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts index 3dc75de..549c24c 100644 --- a/arch/powerpc/boot/dts/canyonlands.dts +++ b/arch/powerpc/boot/dts/canyonlands.dts @@ -190,12 +190,21 @@ /* DMA */ 0x2 &UIC0 0xc 0x4>; }; + AHBDMA: dma@bffd0800 { + compatible = "snps,dma-spear1340"; + reg = <4 0xbffd0800 0x400>; + interrupt-parent = <&UIC3>; + interrupts = <0x5 0x4>; + #dma-cells = <3>; + }; + SATA0: sata@bffd1000 { compatible = "amcc,sata-460ex"; - reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>; + reg = <4 0xbffd1000 0x800>; interrupt-parent = <&UIC3>; - interrupts = <0x0 0x4 /* SATA */ - 0x5 0x4>; /* AHBDMA */ + interrupts = <0x0 0x4>; + dmas = <&AHBDMA 0 1 0>; + dma-names = "sata-dma"; }; POB0: opb { -- cgit v1.1 From 7598469a6184e1017a77ebe78b5b66c52a6afc1c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 11 May 2016 15:42:08 +0200 Subject: ata: dwc: add DMADEVICES dependency The dwc_460ex SATA driver has become available on non-powerpc architectures and may cause randconfig build errors when CONFIG_DMADEVICES is not set and SATA_DWC_OLD_DMA is enabled: warning: (SATA_DWC_OLD_DMA) selects DW_DMAC_CORE which has unmet direct dependencies (DMADEVICES) ERROR: "dw_dma_probe" [drivers/ata/sata_dwc_460ex.ko] undefined! ERROR: "dw_dma_remove" [drivers/ata/sata_dwc_460ex.ko] undefined! This adds an explcit Kconfig dependency to CONFIG_SATA_DWC so we cannot run into broken configurations. While it would also be possible to build the driver with both CONFIG_DMADEVICES and SATA_DWC_OLD_DMA disabled, that case is not useful because there is no fallback to PIO mode when the DMA engine is not usable. Signed-off-by: Arnd Bergmann Fixes: 50b433753df6 ("ata: sata_dwc_460ex: use "dmas" DT property to find dma channel") Reviewed-by: Andy Shevchenko Signed-off-by: Tejun Heo --- drivers/ata/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 3f9bbbf..2fbf355 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -305,6 +305,7 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" + depends on DMADEVICES select GENERIC_PHY help This option enables support for the on-chip SATA controller of the -- cgit v1.1