1) More ACPI fixes, cleanups
2) Minor cleanups for sata_highbank, pata_at32, pata_octeon_cf, sata_rcar 3) pata_legacy: small bug found in opti chipset code (untested fix, due to ancient h/w) 4) sata_fsl: RX water mark config knob, some h/w needs it 5) pata_imx: cleanups, DeviceTree support 6) SCSI<->ATA translator: properly export translator version, not device firmware version -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.13 (GNU/Linux) iQIVAwUAUYBD4SWzCDIBeCsvAQLMKQ/+II9KX8ztaPIil+mm/Uzg47J5p7AUjG6b hk/jnwJTn1M+yvyTe1D1D9LM+9j12XTOCT3Q3u/W7CSFdOc+nMLbI6upty/rHs6L 5N2OvTAA2r4k0CmHe/pXzV0YMkWQE48KQh4S/GZV1wQOt7l4fcfqcx9sEWFPh1dc 4uud+nfeF9P9JG8W6in1hzRqFV++qY/jo7+NQeED24JgjpwpoB/PiJpg6JE4F9/4 WUxWlHQkJyiCar7gCnJGSBAaN3D8t19ptdSx375spzgi1NQZV2AfyuliX1p0vEQo Z8q+3hY6m2kNtj6ZVLmIJIj/k4LUbU4E9hbPV8eIGLeTU46GZVkqZ6th+amCJw40 iHsAyDXuzgne8kvkM9tvzPALauAurbt8PPZFh7aPP05pjI4FXBEO+BMe78TlnevQ F+2VBhIh6C9D7Mo9BIOiMB6sU0mpwqtfH3xaaz39U+cs+xKPa9Ws2lyOVZXGEwTV WaChOpUrN9NNeH9EN3GFA6KY4ovkfYdmc7ahYIBy+xyuh2AiLcsZmyqmEhMyCAQ8 16y0yIoYQNQnC9QooezsuCT9WUqNA0YI+ICQrESX+kviN/wO5LamKN1xI5k/QHR2 6eFuIPat8acHhpa01obOo1HOdvbSuO+uXOtiBToPf+S+d9NFMvVw/j4RkHkTV+Fv xVTbSvP5+TQ= =kLMT -----END PGP SIGNATURE----- Merge tag 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev Pull libata update from Jeff Garzik: - More ACPI fixes, cleanups - Minor cleanups for sata_highbank, pata_at32, pata_octeon_cf, sata_rcar - pata_legacy: small bug found in opti chipset code (untested fix, due to ancient h/w) - sata_fsl: RX water mark config knob, some h/w needs it - pata_imx: cleanups, DeviceTree support - SCSI<->ATA translator: properly export translator version, not device firmware version * tag 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: sata_highbank: Rename proc_name to the module name ACPI/libata: Restore libata.noacpi support [libata] acpi: make ata_ap_acpi_handle not block [libata] SCSI: really use SATL version in VPD pata_imx: add devicetree support pata_imx: use void __iomem * for regs pata_imx: cleanup error path pata_imx: Use devm_clk_get sata_rcar: Convert to devm_ioremap_resource() fsl/sata: create a sysfs entry for rx water mark libata-acpi: remove redundent code for power resource handling sata_highbank: make ahci_highbank_pm_ops static pata_octeon_cf: Use resource_size function pata_legacy: bogus clock in opti82c46x_set_piomode() pata_at32: use module_platform_driver_probe()
This commit is contained in:
Коммит
50528fabeb
|
@ -0,0 +1,17 @@
|
|||
* Freescale i.MX PATA Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: "fsl,imx27-pata"
|
||||
- reg: Address range of the PATA Controller
|
||||
- interrupts: The interrupt of the PATA Controller
|
||||
- clocks: the clocks for the PATA Controller
|
||||
|
||||
Example:
|
||||
|
||||
pata: pata@83fe0000 {
|
||||
compatible = "fsl,imx51-pata", "fsl,imx27-pata";
|
||||
reg = <0x83fe0000 0x4000>;
|
||||
interrupts = <70>;
|
||||
clocks = <&clks 161>;
|
||||
status = "disabled";
|
||||
};
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include "libata.h"
|
||||
|
||||
|
@ -61,7 +60,8 @@ acpi_handle ata_ap_acpi_handle(struct ata_port *ap)
|
|||
if (ap->flags & ATA_FLAG_ACPI_SATA)
|
||||
return NULL;
|
||||
|
||||
return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), ap->port_no);
|
||||
return ap->scsi_host ?
|
||||
DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev) : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(ata_ap_acpi_handle);
|
||||
|
||||
|
@ -77,7 +77,7 @@ acpi_handle ata_dev_acpi_handle(struct ata_device *dev)
|
|||
acpi_integer adr;
|
||||
struct ata_port *ap = dev->link->ap;
|
||||
|
||||
if (dev->flags & ATA_DFLAG_ACPI_DISABLED)
|
||||
if (libata_noacpi || dev->flags & ATA_DFLAG_ACPI_DISABLED)
|
||||
return NULL;
|
||||
|
||||
if (ap->flags & ATA_FLAG_ACPI_SATA) {
|
||||
|
@ -240,28 +240,15 @@ void ata_acpi_dissociate(struct ata_host *host)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_acpi_gtm - execute _GTM
|
||||
* @ap: target ATA port
|
||||
* @gtm: out parameter for _GTM result
|
||||
*
|
||||
* Evaluate _GTM and store the result in @gtm.
|
||||
*
|
||||
* LOCKING:
|
||||
* EH context.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
|
||||
*/
|
||||
int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
|
||||
static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle,
|
||||
struct ata_acpi_gtm *gtm)
|
||||
{
|
||||
struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
|
||||
union acpi_object *out_obj;
|
||||
acpi_status status;
|
||||
int rc = 0;
|
||||
|
||||
status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_GTM", NULL,
|
||||
&output);
|
||||
status = acpi_evaluate_object(handle, "_GTM", NULL, &output);
|
||||
|
||||
rc = -ENOENT;
|
||||
if (status == AE_NOT_FOUND)
|
||||
|
@ -295,6 +282,27 @@ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_acpi_gtm - execute _GTM
|
||||
* @ap: target ATA port
|
||||
* @gtm: out parameter for _GTM result
|
||||
*
|
||||
* Evaluate _GTM and store the result in @gtm.
|
||||
*
|
||||
* LOCKING:
|
||||
* EH context.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
|
||||
*/
|
||||
int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
|
||||
{
|
||||
if (ata_ap_acpi_handle(ap))
|
||||
return __ata_acpi_gtm(ap, ata_ap_acpi_handle(ap), gtm);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ata_acpi_gtm);
|
||||
|
||||
/**
|
||||
|
@ -1020,38 +1028,6 @@ void ata_acpi_on_disable(struct ata_device *dev)
|
|||
ata_acpi_clear_gtf(dev);
|
||||
}
|
||||
|
||||
static void ata_acpi_register_power_resource(struct ata_device *dev)
|
||||
{
|
||||
struct scsi_device *sdev = dev->sdev;
|
||||
acpi_handle handle;
|
||||
|
||||
handle = ata_dev_acpi_handle(dev);
|
||||
if (handle)
|
||||
acpi_dev_pm_add_dependent(handle, &sdev->sdev_gendev);
|
||||
}
|
||||
|
||||
static void ata_acpi_unregister_power_resource(struct ata_device *dev)
|
||||
{
|
||||
struct scsi_device *sdev = dev->sdev;
|
||||
acpi_handle handle;
|
||||
|
||||
handle = ata_dev_acpi_handle(dev);
|
||||
if (handle)
|
||||
acpi_dev_pm_remove_dependent(handle, &sdev->sdev_gendev);
|
||||
}
|
||||
|
||||
void ata_acpi_bind(struct ata_device *dev)
|
||||
{
|
||||
ata_acpi_register_power_resource(dev);
|
||||
if (zpodd_dev_enabled(dev))
|
||||
dev_pm_qos_expose_flags(&dev->sdev->sdev_gendev, 0);
|
||||
}
|
||||
|
||||
void ata_acpi_unbind(struct ata_device *dev)
|
||||
{
|
||||
ata_acpi_unregister_power_resource(dev);
|
||||
}
|
||||
|
||||
static int compat_pci_ata(struct ata_port *ap)
|
||||
{
|
||||
struct device *dev = ap->tdev.parent;
|
||||
|
@ -1071,7 +1047,7 @@ static int compat_pci_ata(struct ata_port *ap)
|
|||
|
||||
static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle)
|
||||
{
|
||||
if (ap->flags & ATA_FLAG_ACPI_SATA)
|
||||
if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA)
|
||||
return -ENODEV;
|
||||
|
||||
*handle = acpi_get_child(DEVICE_ACPI_HANDLE(ap->tdev.parent),
|
||||
|
@ -1080,7 +1056,7 @@ static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle)
|
|||
if (!*handle)
|
||||
return -ENODEV;
|
||||
|
||||
if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
|
||||
if (__ata_acpi_gtm(ap, *handle, &ap->__acpi_init_gtm) == 0)
|
||||
ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <linux/hdreg.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "libata.h"
|
||||
|
@ -2126,7 +2127,6 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
|
|||
memcpy(&rbuf[8], "linux ", 8);
|
||||
memcpy(&rbuf[16], "libata ", 16);
|
||||
memcpy(&rbuf[32], DRV_VERSION, 4);
|
||||
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
|
||||
|
||||
/* we don't store the ATA device signature, so we fake it */
|
||||
|
||||
|
@ -3668,7 +3668,9 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
|
|||
if (!IS_ERR(sdev)) {
|
||||
dev->sdev = sdev;
|
||||
scsi_device_put(sdev);
|
||||
ata_acpi_bind(dev);
|
||||
if (zpodd_dev_enabled(dev))
|
||||
dev_pm_qos_expose_flags(
|
||||
&sdev->sdev_gendev, 0);
|
||||
} else {
|
||||
dev->sdev = NULL;
|
||||
}
|
||||
|
@ -3767,7 +3769,6 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
|
|||
|
||||
if (zpodd_dev_enabled(dev))
|
||||
zpodd_exit(dev);
|
||||
ata_acpi_unbind(dev);
|
||||
|
||||
/* clearing dev->sdev is protected by host lock */
|
||||
sdev = dev->sdev;
|
||||
|
|
|
@ -393,18 +393,7 @@ static struct platform_driver pata_at32_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init pata_at32_init(void)
|
||||
{
|
||||
return platform_driver_probe(&pata_at32_driver, pata_at32_probe);
|
||||
}
|
||||
|
||||
static void __exit pata_at32_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pata_at32_driver);
|
||||
}
|
||||
|
||||
module_init(pata_at32_init);
|
||||
module_exit(pata_at32_exit);
|
||||
module_platform_driver_probe(pata_at32_driver, pata_at32_probe);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("AVR32 SMC/CFC PATA Driver");
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
struct pata_imx_priv {
|
||||
struct clk *clk;
|
||||
/* timings/interrupt/control regs */
|
||||
u8 *host_regs;
|
||||
void __iomem *host_regs;
|
||||
u32 ata_ctl;
|
||||
};
|
||||
|
||||
|
@ -98,6 +98,7 @@ static int pata_imx_probe(struct platform_device *pdev)
|
|||
struct pata_imx_priv *priv;
|
||||
int irq = 0;
|
||||
struct resource *io_res;
|
||||
int ret;
|
||||
|
||||
io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (io_res == NULL)
|
||||
|
@ -112,7 +113,7 @@ static int pata_imx_probe(struct platform_device *pdev)
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->clk = clk_get(&pdev->dev, NULL);
|
||||
priv->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(&pdev->dev, "Failed to get clock\n");
|
||||
return PTR_ERR(priv->clk);
|
||||
|
@ -121,8 +122,10 @@ static int pata_imx_probe(struct platform_device *pdev)
|
|||
clk_prepare_enable(priv->clk);
|
||||
|
||||
host = ata_host_alloc(&pdev->dev, 1);
|
||||
if (!host)
|
||||
goto free_priv;
|
||||
if (!host) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
host->private_data = priv;
|
||||
ap = host->ports[0];
|
||||
|
@ -135,7 +138,8 @@ static int pata_imx_probe(struct platform_device *pdev)
|
|||
resource_size(io_res));
|
||||
if (!priv->host_regs) {
|
||||
dev_err(&pdev->dev, "failed to map IO/CTL base\n");
|
||||
goto free_priv;
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ap->ioaddr.cmd_addr = priv->host_regs + PATA_IMX_DRIVE_DATA;
|
||||
|
@ -158,13 +162,17 @@ static int pata_imx_probe(struct platform_device *pdev)
|
|||
priv->host_regs + PATA_IMX_ATA_INT_EN);
|
||||
|
||||
/* activate */
|
||||
return ata_host_activate(host, irq, ata_sff_interrupt, 0,
|
||||
ret = ata_host_activate(host, irq, ata_sff_interrupt, 0,
|
||||
&pata_imx_sht);
|
||||
|
||||
free_priv:
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
clk_disable_unprepare(priv->clk);
|
||||
clk_put(priv->clk);
|
||||
return -ENOMEM;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pata_imx_remove(struct platform_device *pdev)
|
||||
|
@ -177,7 +185,6 @@ static int pata_imx_remove(struct platform_device *pdev)
|
|||
__raw_writel(0, priv->host_regs + PATA_IMX_ATA_INT_EN);
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
clk_put(priv->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -223,11 +230,20 @@ static const struct dev_pm_ops pata_imx_pm_ops = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static const struct of_device_id imx_pata_dt_ids[] = {
|
||||
{
|
||||
.compatible = "fsl,imx27-pata",
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_driver pata_imx_driver = {
|
||||
.probe = pata_imx_probe,
|
||||
.remove = pata_imx_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = imx_pata_dt_ids,
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &pata_imx_pm_ops,
|
||||
|
|
|
@ -542,7 +542,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|||
u8 sysclk;
|
||||
|
||||
/* Get the clock */
|
||||
sysclk = opti_syscfg(0xAC) & 0xC0; /* BIOS set */
|
||||
sysclk = (opti_syscfg(0xAC) & 0xC0) >> 6; /* BIOS set */
|
||||
|
||||
/* Enter configuration mode */
|
||||
ioread16(ap->ioaddr.error_addr);
|
||||
|
|
|
@ -926,7 +926,7 @@ static int octeon_cf_probe(struct platform_device *pdev)
|
|||
goto free_cf_port;
|
||||
}
|
||||
cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start,
|
||||
res_cs1->end - res_cs1->start + 1);
|
||||
resource_size(res_cs1));
|
||||
|
||||
if (!cs1)
|
||||
goto free_cf_port;
|
||||
|
|
|
@ -285,6 +285,7 @@ struct sata_fsl_host_priv {
|
|||
int irq;
|
||||
int data_snoop;
|
||||
struct device_attribute intr_coalescing;
|
||||
struct device_attribute rx_watermark;
|
||||
};
|
||||
|
||||
static void fsl_sata_set_irq_coalescing(struct ata_host *host,
|
||||
|
@ -343,6 +344,48 @@ static ssize_t fsl_sata_intr_coalescing_store(struct device *dev,
|
|||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t fsl_sata_rx_watermark_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned int rx_watermark;
|
||||
unsigned long flags;
|
||||
struct ata_host *host = dev_get_drvdata(dev);
|
||||
struct sata_fsl_host_priv *host_priv = host->private_data;
|
||||
void __iomem *csr_base = host_priv->csr_base;
|
||||
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
rx_watermark = ioread32(csr_base + TRANSCFG);
|
||||
rx_watermark &= 0x1f;
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
return sprintf(buf, "%d\n", rx_watermark);
|
||||
}
|
||||
|
||||
static ssize_t fsl_sata_rx_watermark_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
unsigned int rx_watermark;
|
||||
unsigned long flags;
|
||||
struct ata_host *host = dev_get_drvdata(dev);
|
||||
struct sata_fsl_host_priv *host_priv = host->private_data;
|
||||
void __iomem *csr_base = host_priv->csr_base;
|
||||
u32 temp;
|
||||
|
||||
if (sscanf(buf, "%d", &rx_watermark) != 1) {
|
||||
printk(KERN_ERR "fsl-sata: wrong parameter format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
temp = ioread32(csr_base + TRANSCFG);
|
||||
temp &= 0xffffffe0;
|
||||
iowrite32(temp | rx_watermark, csr_base + TRANSCFG);
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static inline unsigned int sata_fsl_tag(unsigned int tag,
|
||||
void __iomem *hcr_base)
|
||||
{
|
||||
|
@ -1500,6 +1543,17 @@ static int sata_fsl_probe(struct platform_device *ofdev)
|
|||
if (retval)
|
||||
goto error_exit_with_cleanup;
|
||||
|
||||
host_priv->rx_watermark.show = fsl_sata_rx_watermark_show;
|
||||
host_priv->rx_watermark.store = fsl_sata_rx_watermark_store;
|
||||
sysfs_attr_init(&host_priv->rx_watermark.attr);
|
||||
host_priv->rx_watermark.attr.name = "rx_watermark";
|
||||
host_priv->rx_watermark.attr.mode = S_IRUGO | S_IWUSR;
|
||||
retval = device_create_file(host->dev, &host_priv->rx_watermark);
|
||||
if (retval) {
|
||||
device_remove_file(&ofdev->dev, &host_priv->intr_coalescing);
|
||||
goto error_exit_with_cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_exit_with_cleanup:
|
||||
|
@ -1522,6 +1576,7 @@ static int sata_fsl_remove(struct platform_device *ofdev)
|
|||
struct sata_fsl_host_priv *host_priv = host->private_data;
|
||||
|
||||
device_remove_file(&ofdev->dev, &host_priv->intr_coalescing);
|
||||
device_remove_file(&ofdev->dev, &host_priv->rx_watermark);
|
||||
|
||||
ata_host_detach(host);
|
||||
|
||||
|
|
|
@ -251,7 +251,7 @@ static const struct ata_port_info ahci_highbank_port_info = {
|
|||
};
|
||||
|
||||
static struct scsi_host_template ahci_highbank_platform_sht = {
|
||||
AHCI_SHT("highbank-ahci"),
|
||||
AHCI_SHT("sata_highbank"),
|
||||
};
|
||||
|
||||
static const struct of_device_id ahci_of_match[] = {
|
||||
|
@ -418,7 +418,7 @@ static int ahci_highbank_resume(struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
|
||||
static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
|
||||
ahci_highbank_suspend, ahci_highbank_resume);
|
||||
|
||||
static struct platform_driver ahci_highbank_driver = {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/libata.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#define DRV_NAME "sata_rcar"
|
||||
|
||||
|
@ -799,9 +800,9 @@ static int sata_rcar_probe(struct platform_device *pdev)
|
|||
|
||||
host->private_data = priv;
|
||||
|
||||
priv->base = devm_request_and_ioremap(&pdev->dev, mem);
|
||||
if (!priv->base) {
|
||||
ret = -EADDRNOTAVAIL;
|
||||
priv->base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
if (IS_ERR(priv->base)) {
|
||||
ret = PTR_ERR(priv->base);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче