diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-19 14:04:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-19 14:04:29 -0500 |
commit | 70e66a5079b2b33f142303d31581cf03f7af98fe (patch) | |
tree | 3160fb22716de0407d87ec9de6135127ed7c1fed /drivers/ata/sata_mv.c | |
parent | eca9dfcd0029c8a84b1094bb84a2fb53e4addf6c (diff) | |
parent | 0535f2bc170bc0779ac471faff39f633ca19ab59 (diff) |
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
sata_mv: remove pointless NULL test
pata_hpt3x2n: fix clock turnaround
libata: fix reporting of drained bytes when clearing DRQ
sata_mv: add power management support for the PCI controllers.
sata_mv: store the board_idx into the host private data
pata_octeon_cf: use resource_size(), to fix resource sizing bug
libata: use the WRITE_SAME_16 define
sata_mv: move the PCI bar description initialization code
sata_mv: add power management support for the platform driver
sata_mv: support clkdev framework
sata_mv: increase PIO IORDY timeout
Fixed crazy mode-change in merge.
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r-- | drivers/ata/sata_mv.c | 144 |
1 files changed, 125 insertions, 19 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index a8a7be0d06ff..df8ee325d3ca 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <linux/dmapool.h> | 59 | #include <linux/dmapool.h> |
60 | #include <linux/dma-mapping.h> | 60 | #include <linux/dma-mapping.h> |
61 | #include <linux/device.h> | 61 | #include <linux/device.h> |
62 | #include <linux/clk.h> | ||
62 | #include <linux/platform_device.h> | 63 | #include <linux/platform_device.h> |
63 | #include <linux/ata_platform.h> | 64 | #include <linux/ata_platform.h> |
64 | #include <linux/mbus.h> | 65 | #include <linux/mbus.h> |
@@ -538,6 +539,7 @@ struct mv_port_signal { | |||
538 | 539 | ||
539 | struct mv_host_priv { | 540 | struct mv_host_priv { |
540 | u32 hp_flags; | 541 | u32 hp_flags; |
542 | unsigned int board_idx; | ||
541 | u32 main_irq_mask; | 543 | u32 main_irq_mask; |
542 | struct mv_port_signal signal[8]; | 544 | struct mv_port_signal signal[8]; |
543 | const struct mv_hw_ops *ops; | 545 | const struct mv_hw_ops *ops; |
@@ -548,6 +550,10 @@ struct mv_host_priv { | |||
548 | u32 irq_cause_offset; | 550 | u32 irq_cause_offset; |
549 | u32 irq_mask_offset; | 551 | u32 irq_mask_offset; |
550 | u32 unmask_all_irqs; | 552 | u32 unmask_all_irqs; |
553 | |||
554 | #if defined(CONFIG_HAVE_CLK) | ||
555 | struct clk *clk; | ||
556 | #endif | ||
551 | /* | 557 | /* |
552 | * These consistent DMA memory pools give us guaranteed | 558 | * These consistent DMA memory pools give us guaranteed |
553 | * alignment for hardware-accessed data structures, | 559 | * alignment for hardware-accessed data structures, |
@@ -2775,7 +2781,7 @@ static void mv_port_intr(struct ata_port *ap, u32 port_cause) | |||
2775 | struct mv_port_priv *pp; | 2781 | struct mv_port_priv *pp; |
2776 | int edma_was_enabled; | 2782 | int edma_was_enabled; |
2777 | 2783 | ||
2778 | if (!ap || (ap->flags & ATA_FLAG_DISABLED)) { | 2784 | if (ap->flags & ATA_FLAG_DISABLED) { |
2779 | mv_unexpected_intr(ap, 0); | 2785 | mv_unexpected_intr(ap, 0); |
2780 | return; | 2786 | return; |
2781 | } | 2787 | } |
@@ -3393,7 +3399,7 @@ static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv, | |||
3393 | ZERO(0x024); /* respq outp */ | 3399 | ZERO(0x024); /* respq outp */ |
3394 | ZERO(0x020); /* respq inp */ | 3400 | ZERO(0x020); /* respq inp */ |
3395 | ZERO(0x02c); /* test control */ | 3401 | ZERO(0x02c); /* test control */ |
3396 | writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); | 3402 | writel(0x800, port_mmio + EDMA_IORDY_TMOUT); |
3397 | } | 3403 | } |
3398 | 3404 | ||
3399 | #undef ZERO | 3405 | #undef ZERO |
@@ -3854,7 +3860,6 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) | |||
3854 | /** | 3860 | /** |
3855 | * mv_init_host - Perform some early initialization of the host. | 3861 | * mv_init_host - Perform some early initialization of the host. |
3856 | * @host: ATA host to initialize | 3862 | * @host: ATA host to initialize |
3857 | * @board_idx: controller index | ||
3858 | * | 3863 | * |
3859 | * If possible, do an early global reset of the host. Then do | 3864 | * If possible, do an early global reset of the host. Then do |
3860 | * our port init and clear/unmask all/relevant host interrupts. | 3865 | * our port init and clear/unmask all/relevant host interrupts. |
@@ -3862,13 +3867,13 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) | |||
3862 | * LOCKING: | 3867 | * LOCKING: |
3863 | * Inherited from caller. | 3868 | * Inherited from caller. |
3864 | */ | 3869 | */ |
3865 | static int mv_init_host(struct ata_host *host, unsigned int board_idx) | 3870 | static int mv_init_host(struct ata_host *host) |
3866 | { | 3871 | { |
3867 | int rc = 0, n_hc, port, hc; | 3872 | int rc = 0, n_hc, port, hc; |
3868 | struct mv_host_priv *hpriv = host->private_data; | 3873 | struct mv_host_priv *hpriv = host->private_data; |
3869 | void __iomem *mmio = hpriv->base; | 3874 | void __iomem *mmio = hpriv->base; |
3870 | 3875 | ||
3871 | rc = mv_chip_id(host, board_idx); | 3876 | rc = mv_chip_id(host, hpriv->board_idx); |
3872 | if (rc) | 3877 | if (rc) |
3873 | goto done; | 3878 | goto done; |
3874 | 3879 | ||
@@ -3905,14 +3910,6 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) | |||
3905 | void __iomem *port_mmio = mv_port_base(mmio, port); | 3910 | void __iomem *port_mmio = mv_port_base(mmio, port); |
3906 | 3911 | ||
3907 | mv_port_init(&ap->ioaddr, port_mmio); | 3912 | mv_port_init(&ap->ioaddr, port_mmio); |
3908 | |||
3909 | #ifdef CONFIG_PCI | ||
3910 | if (!IS_SOC(hpriv)) { | ||
3911 | unsigned int offset = port_mmio - mmio; | ||
3912 | ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio"); | ||
3913 | ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port"); | ||
3914 | } | ||
3915 | #endif | ||
3916 | } | 3913 | } |
3917 | 3914 | ||
3918 | for (hc = 0; hc < n_hc; hc++) { | 3915 | for (hc = 0; hc < n_hc; hc++) { |
@@ -4035,12 +4032,21 @@ static int mv_platform_probe(struct platform_device *pdev) | |||
4035 | return -ENOMEM; | 4032 | return -ENOMEM; |
4036 | host->private_data = hpriv; | 4033 | host->private_data = hpriv; |
4037 | hpriv->n_ports = n_ports; | 4034 | hpriv->n_ports = n_ports; |
4035 | hpriv->board_idx = chip_soc; | ||
4038 | 4036 | ||
4039 | host->iomap = NULL; | 4037 | host->iomap = NULL; |
4040 | hpriv->base = devm_ioremap(&pdev->dev, res->start, | 4038 | hpriv->base = devm_ioremap(&pdev->dev, res->start, |
4041 | resource_size(res)); | 4039 | resource_size(res)); |
4042 | hpriv->base -= SATAHC0_REG_BASE; | 4040 | hpriv->base -= SATAHC0_REG_BASE; |
4043 | 4041 | ||
4042 | #if defined(CONFIG_HAVE_CLK) | ||
4043 | hpriv->clk = clk_get(&pdev->dev, NULL); | ||
4044 | if (IS_ERR(hpriv->clk)) | ||
4045 | dev_notice(&pdev->dev, "cannot get clkdev\n"); | ||
4046 | else | ||
4047 | clk_enable(hpriv->clk); | ||
4048 | #endif | ||
4049 | |||
4044 | /* | 4050 | /* |
4045 | * (Re-)program MBUS remapping windows if we are asked to. | 4051 | * (Re-)program MBUS remapping windows if we are asked to. |
4046 | */ | 4052 | */ |
@@ -4049,12 +4055,12 @@ static int mv_platform_probe(struct platform_device *pdev) | |||
4049 | 4055 | ||
4050 | rc = mv_create_dma_pools(hpriv, &pdev->dev); | 4056 | rc = mv_create_dma_pools(hpriv, &pdev->dev); |
4051 | if (rc) | 4057 | if (rc) |
4052 | return rc; | 4058 | goto err; |
4053 | 4059 | ||
4054 | /* initialize adapter */ | 4060 | /* initialize adapter */ |
4055 | rc = mv_init_host(host, chip_soc); | 4061 | rc = mv_init_host(host); |
4056 | if (rc) | 4062 | if (rc) |
4057 | return rc; | 4063 | goto err; |
4058 | 4064 | ||
4059 | dev_printk(KERN_INFO, &pdev->dev, | 4065 | dev_printk(KERN_INFO, &pdev->dev, |
4060 | "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH, | 4066 | "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH, |
@@ -4062,6 +4068,15 @@ static int mv_platform_probe(struct platform_device *pdev) | |||
4062 | 4068 | ||
4063 | return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt, | 4069 | return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt, |
4064 | IRQF_SHARED, &mv6_sht); | 4070 | IRQF_SHARED, &mv6_sht); |
4071 | err: | ||
4072 | #if defined(CONFIG_HAVE_CLK) | ||
4073 | if (!IS_ERR(hpriv->clk)) { | ||
4074 | clk_disable(hpriv->clk); | ||
4075 | clk_put(hpriv->clk); | ||
4076 | } | ||
4077 | #endif | ||
4078 | |||
4079 | return rc; | ||
4065 | } | 4080 | } |
4066 | 4081 | ||
4067 | /* | 4082 | /* |
@@ -4076,14 +4091,66 @@ static int __devexit mv_platform_remove(struct platform_device *pdev) | |||
4076 | { | 4091 | { |
4077 | struct device *dev = &pdev->dev; | 4092 | struct device *dev = &pdev->dev; |
4078 | struct ata_host *host = dev_get_drvdata(dev); | 4093 | struct ata_host *host = dev_get_drvdata(dev); |
4079 | 4094 | #if defined(CONFIG_HAVE_CLK) | |
4095 | struct mv_host_priv *hpriv = host->private_data; | ||
4096 | #endif | ||
4080 | ata_host_detach(host); | 4097 | ata_host_detach(host); |
4098 | |||
4099 | #if defined(CONFIG_HAVE_CLK) | ||
4100 | if (!IS_ERR(hpriv->clk)) { | ||
4101 | clk_disable(hpriv->clk); | ||
4102 | clk_put(hpriv->clk); | ||
4103 | } | ||
4104 | #endif | ||
4081 | return 0; | 4105 | return 0; |
4082 | } | 4106 | } |
4083 | 4107 | ||
4108 | #ifdef CONFIG_PM | ||
4109 | static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state) | ||
4110 | { | ||
4111 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
4112 | if (host) | ||
4113 | return ata_host_suspend(host, state); | ||
4114 | else | ||
4115 | return 0; | ||
4116 | } | ||
4117 | |||
4118 | static int mv_platform_resume(struct platform_device *pdev) | ||
4119 | { | ||
4120 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
4121 | int ret; | ||
4122 | |||
4123 | if (host) { | ||
4124 | struct mv_host_priv *hpriv = host->private_data; | ||
4125 | const struct mv_sata_platform_data *mv_platform_data = \ | ||
4126 | pdev->dev.platform_data; | ||
4127 | /* | ||
4128 | * (Re-)program MBUS remapping windows if we are asked to. | ||
4129 | */ | ||
4130 | if (mv_platform_data->dram != NULL) | ||
4131 | mv_conf_mbus_windows(hpriv, mv_platform_data->dram); | ||
4132 | |||
4133 | /* initialize adapter */ | ||
4134 | ret = mv_init_host(host); | ||
4135 | if (ret) { | ||
4136 | printk(KERN_ERR DRV_NAME ": Error during HW init\n"); | ||
4137 | return ret; | ||
4138 | } | ||
4139 | ata_host_resume(host); | ||
4140 | } | ||
4141 | |||
4142 | return 0; | ||
4143 | } | ||
4144 | #else | ||
4145 | #define mv_platform_suspend NULL | ||
4146 | #define mv_platform_resume NULL | ||
4147 | #endif | ||
4148 | |||
4084 | static struct platform_driver mv_platform_driver = { | 4149 | static struct platform_driver mv_platform_driver = { |
4085 | .probe = mv_platform_probe, | 4150 | .probe = mv_platform_probe, |
4086 | .remove = __devexit_p(mv_platform_remove), | 4151 | .remove = __devexit_p(mv_platform_remove), |
4152 | .suspend = mv_platform_suspend, | ||
4153 | .resume = mv_platform_resume, | ||
4087 | .driver = { | 4154 | .driver = { |
4088 | .name = DRV_NAME, | 4155 | .name = DRV_NAME, |
4089 | .owner = THIS_MODULE, | 4156 | .owner = THIS_MODULE, |
@@ -4094,6 +4161,9 @@ static struct platform_driver mv_platform_driver = { | |||
4094 | #ifdef CONFIG_PCI | 4161 | #ifdef CONFIG_PCI |
4095 | static int mv_pci_init_one(struct pci_dev *pdev, | 4162 | static int mv_pci_init_one(struct pci_dev *pdev, |
4096 | const struct pci_device_id *ent); | 4163 | const struct pci_device_id *ent); |
4164 | #ifdef CONFIG_PM | ||
4165 | static int mv_pci_device_resume(struct pci_dev *pdev); | ||
4166 | #endif | ||
4097 | 4167 | ||
4098 | 4168 | ||
4099 | static struct pci_driver mv_pci_driver = { | 4169 | static struct pci_driver mv_pci_driver = { |
@@ -4101,6 +4171,11 @@ static struct pci_driver mv_pci_driver = { | |||
4101 | .id_table = mv_pci_tbl, | 4171 | .id_table = mv_pci_tbl, |
4102 | .probe = mv_pci_init_one, | 4172 | .probe = mv_pci_init_one, |
4103 | .remove = ata_pci_remove_one, | 4173 | .remove = ata_pci_remove_one, |
4174 | #ifdef CONFIG_PM | ||
4175 | .suspend = ata_pci_device_suspend, | ||
4176 | .resume = mv_pci_device_resume, | ||
4177 | #endif | ||
4178 | |||
4104 | }; | 4179 | }; |
4105 | 4180 | ||
4106 | /* move to PCI layer or libata core? */ | 4181 | /* move to PCI layer or libata core? */ |
@@ -4194,7 +4269,7 @@ static int mv_pci_init_one(struct pci_dev *pdev, | |||
4194 | const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL }; | 4269 | const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL }; |
4195 | struct ata_host *host; | 4270 | struct ata_host *host; |
4196 | struct mv_host_priv *hpriv; | 4271 | struct mv_host_priv *hpriv; |
4197 | int n_ports, rc; | 4272 | int n_ports, port, rc; |
4198 | 4273 | ||
4199 | if (!printed_version++) | 4274 | if (!printed_version++) |
4200 | dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); | 4275 | dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); |
@@ -4208,6 +4283,7 @@ static int mv_pci_init_one(struct pci_dev *pdev, | |||
4208 | return -ENOMEM; | 4283 | return -ENOMEM; |
4209 | host->private_data = hpriv; | 4284 | host->private_data = hpriv; |
4210 | hpriv->n_ports = n_ports; | 4285 | hpriv->n_ports = n_ports; |
4286 | hpriv->board_idx = board_idx; | ||
4211 | 4287 | ||
4212 | /* acquire resources */ | 4288 | /* acquire resources */ |
4213 | rc = pcim_enable_device(pdev); | 4289 | rc = pcim_enable_device(pdev); |
@@ -4230,8 +4306,17 @@ static int mv_pci_init_one(struct pci_dev *pdev, | |||
4230 | if (rc) | 4306 | if (rc) |
4231 | return rc; | 4307 | return rc; |
4232 | 4308 | ||
4309 | for (port = 0; port < host->n_ports; port++) { | ||
4310 | struct ata_port *ap = host->ports[port]; | ||
4311 | void __iomem *port_mmio = mv_port_base(hpriv->base, port); | ||
4312 | unsigned int offset = port_mmio - hpriv->base; | ||
4313 | |||
4314 | ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio"); | ||
4315 | ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port"); | ||
4316 | } | ||
4317 | |||
4233 | /* initialize adapter */ | 4318 | /* initialize adapter */ |
4234 | rc = mv_init_host(host, board_idx); | 4319 | rc = mv_init_host(host); |
4235 | if (rc) | 4320 | if (rc) |
4236 | return rc; | 4321 | return rc; |
4237 | 4322 | ||
@@ -4247,6 +4332,27 @@ static int mv_pci_init_one(struct pci_dev *pdev, | |||
4247 | return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED, | 4332 | return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED, |
4248 | IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht); | 4333 | IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht); |
4249 | } | 4334 | } |
4335 | |||
4336 | #ifdef CONFIG_PM | ||
4337 | static int mv_pci_device_resume(struct pci_dev *pdev) | ||
4338 | { | ||
4339 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
4340 | int rc; | ||
4341 | |||
4342 | rc = ata_pci_device_do_resume(pdev); | ||
4343 | if (rc) | ||
4344 | return rc; | ||
4345 | |||
4346 | /* initialize adapter */ | ||
4347 | rc = mv_init_host(host); | ||
4348 | if (rc) | ||
4349 | return rc; | ||
4350 | |||
4351 | ata_host_resume(host); | ||
4352 | |||
4353 | return 0; | ||
4354 | } | ||
4355 | #endif | ||
4250 | #endif | 4356 | #endif |
4251 | 4357 | ||
4252 | static int mv_platform_probe(struct platform_device *pdev); | 4358 | static int mv_platform_probe(struct platform_device *pdev); |