You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'at91' into devel
This commit is contained in:
@@ -496,7 +496,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
arg = arg->common.next;
|
||||
}
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Package List length (%X) larger than NumElements count (%X), truncated\n",
|
||||
i, element_count));
|
||||
} else if (i < element_count) {
|
||||
|
||||
@@ -71,7 +71,7 @@ static DEFINE_MUTEX(performance_mutex);
|
||||
* 1 -> ignore _PPC totally -> forced by user through boot param
|
||||
*/
|
||||
static int ignore_ppc = -1;
|
||||
module_param(ignore_ppc, uint, 0644);
|
||||
module_param(ignore_ppc, int, 0644);
|
||||
MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
|
||||
"limited by BIOS, this should help");
|
||||
|
||||
|
||||
@@ -107,6 +107,13 @@ static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
|
||||
if (wait_event_timeout(hc->wait, smb_check_done(hc),
|
||||
msecs_to_jiffies(timeout)))
|
||||
return 0;
|
||||
/*
|
||||
* After the timeout happens, OS will try to check the status of SMbus.
|
||||
* If the status is what OS expected, it will be regarded as the bogus
|
||||
* timeout.
|
||||
*/
|
||||
if (smb_check_done(hc))
|
||||
return 0;
|
||||
else
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
@@ -300,6 +300,8 @@ int __init acpi_table_init(void)
|
||||
|
||||
static int __init acpi_parse_apic_instance(char *str)
|
||||
{
|
||||
if (!str)
|
||||
return -EINVAL;
|
||||
|
||||
acpi_apic_instance = simple_strtoul(str, NULL, 0);
|
||||
|
||||
|
||||
+4
-2
@@ -448,8 +448,10 @@ config PATA_MARVELL
|
||||
tristate "Marvell PATA support via legacy mode"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables limited support for the Marvell 88SE6145 ATA
|
||||
controller.
|
||||
This option enables limited support for the Marvell 88SE61xx ATA
|
||||
controllers. If you wish to use only the SATA ports then select
|
||||
the AHCI driver alone. If you wish to the use the PATA port or
|
||||
both SATA and PATA include this driver.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
||||
+20
-1
@@ -420,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = {
|
||||
/* board_ahci_mv */
|
||||
{
|
||||
AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
|
||||
AHCI_HFLAG_MV_PATA),
|
||||
AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
|
||||
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
@@ -487,7 +487,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
|
||||
{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
|
||||
|
||||
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
|
||||
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
@@ -610,6 +612,15 @@ module_param(ahci_em_messages, int, 0444);
|
||||
MODULE_PARM_DESC(ahci_em_messages,
|
||||
"Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
|
||||
|
||||
#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
|
||||
static int marvell_enable;
|
||||
#else
|
||||
static int marvell_enable = 1;
|
||||
#endif
|
||||
module_param(marvell_enable, int, 0644);
|
||||
MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
|
||||
|
||||
|
||||
static inline int ahci_nr_ports(u32 cap)
|
||||
{
|
||||
return (cap & 0x1f) + 1;
|
||||
@@ -732,6 +743,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
|
||||
"MV_AHCI HACK: port_map %x -> %x\n",
|
||||
port_map,
|
||||
port_map & mv);
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
|
||||
|
||||
port_map &= mv;
|
||||
}
|
||||
@@ -2533,6 +2546,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (!printed_version++)
|
||||
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
|
||||
|
||||
/* The AHCI driver can only drive the SATA ports, the PATA driver
|
||||
can drive them all so if both drivers are selected make sure
|
||||
AHCI stays out of the way */
|
||||
if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
|
||||
return -ENODEV;
|
||||
|
||||
/* acquire resources */
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc)
|
||||
|
||||
@@ -1315,11 +1315,6 @@ fsm_start:
|
||||
break;
|
||||
|
||||
case HSM_ST_ERR:
|
||||
/* make sure qc->err_mask is available to
|
||||
* know what's wrong and recover
|
||||
*/
|
||||
WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
|
||||
|
||||
ap->hsm_task_state = HSM_ST_IDLE;
|
||||
|
||||
/* complete taskfile transaction */
|
||||
|
||||
+45
-20
@@ -20,7 +20,42 @@
|
||||
#include <linux/ata.h>
|
||||
|
||||
#define DRV_NAME "pata_marvell"
|
||||
#define DRV_VERSION "0.1.4"
|
||||
#define DRV_VERSION "0.1.6"
|
||||
|
||||
/**
|
||||
* marvell_pata_active - check if PATA is active
|
||||
* @pdev: PCI device
|
||||
*
|
||||
* Returns 1 if the PATA port may be active. We know how to check this
|
||||
* for the 6145 but not the other devices
|
||||
*/
|
||||
|
||||
static int marvell_pata_active(struct pci_dev *pdev)
|
||||
{
|
||||
int i;
|
||||
u32 devices;
|
||||
void __iomem *barp;
|
||||
|
||||
/* We don't yet know how to do this for other devices */
|
||||
if (pdev->device != 0x6145)
|
||||
return 1;
|
||||
|
||||
barp = pci_iomap(pdev, 5, 0x10);
|
||||
if (barp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
printk("BAR5:");
|
||||
for(i = 0; i <= 0x0F; i++)
|
||||
printk("%02X:%02X ", i, ioread8(barp + i));
|
||||
printk("\n");
|
||||
|
||||
devices = ioread32(barp + 0x0C);
|
||||
pci_iounmap(pdev, barp);
|
||||
|
||||
if (devices & 0x10)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* marvell_pre_reset - check for 40/80 pin
|
||||
@@ -34,26 +69,10 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
|
||||
{
|
||||
struct ata_port *ap = link->ap;
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
u32 devices;
|
||||
void __iomem *barp;
|
||||
int i;
|
||||
|
||||
/* Check if our port is enabled */
|
||||
|
||||
barp = pci_iomap(pdev, 5, 0x10);
|
||||
if (barp == NULL)
|
||||
return -ENOMEM;
|
||||
printk("BAR5:");
|
||||
for(i = 0; i <= 0x0F; i++)
|
||||
printk("%02X:%02X ", i, ioread8(barp + i));
|
||||
printk("\n");
|
||||
|
||||
devices = ioread32(barp + 0x0C);
|
||||
pci_iounmap(pdev, barp);
|
||||
|
||||
if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
|
||||
(!(devices & 0x10))) /* PATA enable ? */
|
||||
return -ENOENT;
|
||||
if (pdev->device == 0x6145 && ap->port_no == 0 &&
|
||||
!marvell_pata_active(pdev)) /* PATA enable ? */
|
||||
return -ENOENT;
|
||||
|
||||
return ata_sff_prereset(link, deadline);
|
||||
}
|
||||
@@ -128,6 +147,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
|
||||
if (pdev->device == 0x6101)
|
||||
ppi[1] = &ata_dummy_port_info;
|
||||
|
||||
#if defined(CONFIG_AHCI) || defined(CONFIG_AHCI_MODULE)
|
||||
if (!marvell_pata_active(pdev)) {
|
||||
printk(KERN_INFO DRV_NAME ": PATA port not active, deferring to AHCI driver.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -322,9 +322,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
|
||||
/* Try to acquire MMIO resources and fallback to PIO if
|
||||
* that fails
|
||||
*/
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME);
|
||||
if (rc)
|
||||
goto use_ioports;
|
||||
|
||||
@@ -667,7 +667,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
|
||||
{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
|
||||
{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
|
||||
/* RocketRAID 1740/174x have different identifiers */
|
||||
/* RocketRAID 1720/174x have different identifiers */
|
||||
{ PCI_VDEVICE(TTI, 0x1720), chip_6042 },
|
||||
{ PCI_VDEVICE(TTI, 0x1740), chip_508x },
|
||||
{ PCI_VDEVICE(TTI, 0x1742), chip_508x },
|
||||
|
||||
|
||||
+1
-18
@@ -309,8 +309,6 @@ static void nv_nf2_freeze(struct ata_port *ap);
|
||||
static void nv_nf2_thaw(struct ata_port *ap);
|
||||
static void nv_ck804_freeze(struct ata_port *ap);
|
||||
static void nv_ck804_thaw(struct ata_port *ap);
|
||||
static int nv_hardreset(struct ata_link *link, unsigned int *class,
|
||||
unsigned long deadline);
|
||||
static int nv_adma_slave_config(struct scsi_device *sdev);
|
||||
static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||
static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
|
||||
@@ -407,7 +405,7 @@ static struct scsi_host_template nv_swncq_sht = {
|
||||
|
||||
static struct ata_port_operations nv_generic_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
.hardreset = nv_hardreset,
|
||||
.hardreset = ATA_OP_NULL,
|
||||
.scr_read = nv_scr_read,
|
||||
.scr_write = nv_scr_write,
|
||||
};
|
||||
@@ -1588,21 +1586,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
|
||||
ata_sff_thaw(ap);
|
||||
}
|
||||
|
||||
static int nv_hardreset(struct ata_link *link, unsigned int *class,
|
||||
unsigned long deadline)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* SATA hardreset fails to retrieve proper device signature on
|
||||
* some controllers. Request follow up SRST. For more info,
|
||||
* see http://bugzilla.kernel.org/show_bug.cgi?id=3352
|
||||
*/
|
||||
rc = sata_sff_hardreset(link, class, deadline);
|
||||
if (rc)
|
||||
return rc;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static void nv_adma_error_handler(struct ata_port *ap)
|
||||
{
|
||||
struct nv_adma_port_priv *pp = ap->private_data;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
@@ -151,13 +152,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
|
||||
*/
|
||||
static int verify_pmtmr_rate(void)
|
||||
{
|
||||
u32 value1, value2;
|
||||
cycle_t value1, value2;
|
||||
unsigned long count, delta;
|
||||
|
||||
mach_prepare_counter();
|
||||
value1 = read_pmtmr();
|
||||
value1 = clocksource_acpi_pm.read();
|
||||
mach_countup(&count);
|
||||
value2 = read_pmtmr();
|
||||
value2 = clocksource_acpi_pm.read();
|
||||
delta = (value2 - value1) & ACPI_PM_MASK;
|
||||
|
||||
/* Check that the PMTMR delta is within 5% of what we expect */
|
||||
@@ -175,10 +176,13 @@ static int verify_pmtmr_rate(void)
|
||||
#define verify_pmtmr_rate() (0)
|
||||
#endif
|
||||
|
||||
/* Number of monotonicity checks to perform during initialization */
|
||||
#define ACPI_PM_MONOTONICITY_CHECKS 10
|
||||
|
||||
static int __init init_acpi_pm_clocksource(void)
|
||||
{
|
||||
u32 value1, value2;
|
||||
unsigned int i;
|
||||
cycle_t value1, value2;
|
||||
unsigned int i, j, good = 0;
|
||||
|
||||
if (!pmtmr_ioport)
|
||||
return -ENODEV;
|
||||
@@ -187,24 +191,32 @@ static int __init init_acpi_pm_clocksource(void)
|
||||
clocksource_acpi_pm.shift);
|
||||
|
||||
/* "verify" this timing source: */
|
||||
value1 = read_pmtmr();
|
||||
for (i = 0; i < 10000; i++) {
|
||||
value2 = read_pmtmr();
|
||||
if (value2 == value1)
|
||||
continue;
|
||||
if (value2 > value1)
|
||||
goto pm_good;
|
||||
if ((value2 < value1) && ((value2) < 0xFFF))
|
||||
goto pm_good;
|
||||
printk(KERN_INFO "PM-Timer had inconsistent results:"
|
||||
" 0x%#x, 0x%#x - aborting.\n", value1, value2);
|
||||
return -EINVAL;
|
||||
for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
|
||||
value1 = clocksource_acpi_pm.read();
|
||||
for (i = 0; i < 10000; i++) {
|
||||
value2 = clocksource_acpi_pm.read();
|
||||
if (value2 == value1)
|
||||
continue;
|
||||
if (value2 > value1)
|
||||
good++;
|
||||
break;
|
||||
if ((value2 < value1) && ((value2) < 0xFFF))
|
||||
good++;
|
||||
break;
|
||||
printk(KERN_INFO "PM-Timer had inconsistent results:"
|
||||
" 0x%#llx, 0x%#llx - aborting.\n",
|
||||
value1, value2);
|
||||
return -EINVAL;
|
||||
}
|
||||
udelay(300 * i);
|
||||
}
|
||||
|
||||
if (good != ACPI_PM_MONOTONICITY_CHECKS) {
|
||||
printk(KERN_INFO "PM-Timer failed consistency check "
|
||||
" (0x%#llx) - aborting.\n", value1);
|
||||
return -ENODEV;
|
||||
}
|
||||
printk(KERN_INFO "PM-Timer had no reasonable result:"
|
||||
" 0x%#x - aborting.\n", value1);
|
||||
return -ENODEV;
|
||||
|
||||
pm_good:
|
||||
if (verify_pmtmr_rate() != 0)
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
@@ -31,13 +31,84 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
/* Transmit operation: */
|
||||
/* */
|
||||
/* 0 byte transmit */
|
||||
/* BUS: S A8 ACK P */
|
||||
/* IRQ: DTE WAIT */
|
||||
/* ICIC: */
|
||||
/* ICCR: 0x94 0x90 */
|
||||
/* ICDR: A8 */
|
||||
/* */
|
||||
/* 1 byte transmit */
|
||||
/* BUS: S A8 ACK D8(1) ACK P */
|
||||
/* IRQ: DTE WAIT WAIT */
|
||||
/* ICIC: -DTE */
|
||||
/* ICCR: 0x94 0x90 */
|
||||
/* ICDR: A8 D8(1) */
|
||||
/* */
|
||||
/* 2 byte transmit */
|
||||
/* BUS: S A8 ACK D8(1) ACK D8(2) ACK P */
|
||||
/* IRQ: DTE WAIT WAIT WAIT */
|
||||
/* ICIC: -DTE */
|
||||
/* ICCR: 0x94 0x90 */
|
||||
/* ICDR: A8 D8(1) D8(2) */
|
||||
/* */
|
||||
/* 3 bytes or more, +---------+ gets repeated */
|
||||
/* */
|
||||
/* */
|
||||
/* Receive operation: */
|
||||
/* */
|
||||
/* 0 byte receive - not supported since slave may hold SDA low */
|
||||
/* */
|
||||
/* 1 byte receive [TX] | [RX] */
|
||||
/* BUS: S A8 ACK | D8(1) ACK P */
|
||||
/* IRQ: DTE WAIT | WAIT DTE */
|
||||
/* ICIC: -DTE | +DTE */
|
||||
/* ICCR: 0x94 0x81 | 0xc0 */
|
||||
/* ICDR: A8 | D8(1) */
|
||||
/* */
|
||||
/* 2 byte receive [TX]| [RX] */
|
||||
/* BUS: S A8 ACK | D8(1) ACK D8(2) ACK P */
|
||||
/* IRQ: DTE WAIT | WAIT WAIT DTE */
|
||||
/* ICIC: -DTE | +DTE */
|
||||
/* ICCR: 0x94 0x81 | 0xc0 */
|
||||
/* ICDR: A8 | D8(1) D8(2) */
|
||||
/* */
|
||||
/* 3 byte receive [TX] | [RX] */
|
||||
/* BUS: S A8 ACK | D8(1) ACK D8(2) ACK D8(3) ACK P */
|
||||
/* IRQ: DTE WAIT | WAIT WAIT WAIT DTE */
|
||||
/* ICIC: -DTE | +DTE */
|
||||
/* ICCR: 0x94 0x81 | 0xc0 */
|
||||
/* ICDR: A8 | D8(1) D8(2) D8(3) */
|
||||
/* */
|
||||
/* 4 bytes or more, this part is repeated +---------+ */
|
||||
/* */
|
||||
/* */
|
||||
/* Interrupt order and BUSY flag */
|
||||
/* ___ _ */
|
||||
/* SDA ___\___XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAA___/ */
|
||||
/* SCL \_/1\_/2\_/3\_/4\_/5\_/6\_/7\_/8\___/9\_____/ */
|
||||
/* */
|
||||
/* S D7 D6 D5 D4 D3 D2 D1 D0 P */
|
||||
/* ___ */
|
||||
/* WAIT IRQ ________________________________/ \___________ */
|
||||
/* TACK IRQ ____________________________________/ \_______ */
|
||||
/* DTE IRQ __________________________________________/ \_ */
|
||||
/* AL IRQ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
||||
/* _______________________________________________ */
|
||||
/* BUSY __/ \_ */
|
||||
/* */
|
||||
|
||||
enum sh_mobile_i2c_op {
|
||||
OP_START = 0,
|
||||
OP_TX_ONLY,
|
||||
OP_TX_FIRST,
|
||||
OP_TX,
|
||||
OP_TX_STOP,
|
||||
OP_TX_TO_RX,
|
||||
OP_RX_ONLY,
|
||||
OP_RX,
|
||||
OP_RX_STOP,
|
||||
OP_RX_STOP_DATA,
|
||||
};
|
||||
|
||||
struct sh_mobile_i2c_data {
|
||||
@@ -127,25 +198,34 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
|
||||
spin_lock_irqsave(&pd->lock, flags);
|
||||
|
||||
switch (op) {
|
||||
case OP_START:
|
||||
case OP_START: /* issue start and trigger DTE interrupt */
|
||||
iowrite8(0x94, ICCR(pd));
|
||||
break;
|
||||
case OP_TX_ONLY:
|
||||
case OP_TX_FIRST: /* disable DTE interrupt and write data */
|
||||
iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd));
|
||||
iowrite8(data, ICDR(pd));
|
||||
break;
|
||||
case OP_TX_STOP:
|
||||
case OP_TX: /* write data */
|
||||
iowrite8(data, ICDR(pd));
|
||||
break;
|
||||
case OP_TX_STOP: /* write data and issue a stop afterwards */
|
||||
iowrite8(data, ICDR(pd));
|
||||
iowrite8(0x90, ICCR(pd));
|
||||
iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd));
|
||||
break;
|
||||
case OP_TX_TO_RX:
|
||||
iowrite8(data, ICDR(pd));
|
||||
case OP_TX_TO_RX: /* select read mode */
|
||||
iowrite8(0x81, ICCR(pd));
|
||||
break;
|
||||
case OP_RX_ONLY:
|
||||
case OP_RX: /* just read data */
|
||||
ret = ioread8(ICDR(pd));
|
||||
break;
|
||||
case OP_RX_STOP:
|
||||
case OP_RX_STOP: /* enable DTE interrupt, issue stop */
|
||||
iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE,
|
||||
ICIC(pd));
|
||||
iowrite8(0xc0, ICCR(pd));
|
||||
break;
|
||||
case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */
|
||||
iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE,
|
||||
ICIC(pd));
|
||||
ret = ioread8(ICDR(pd));
|
||||
iowrite8(0xc0, ICCR(pd));
|
||||
break;
|
||||
@@ -157,58 +237,120 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd)
|
||||
{
|
||||
if (pd->pos == -1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_mobile_i2c_is_last_byte(struct sh_mobile_i2c_data *pd)
|
||||
{
|
||||
if (pd->pos == (pd->msg->len - 1))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd,
|
||||
unsigned char *buf)
|
||||
{
|
||||
switch (pd->pos) {
|
||||
case -1:
|
||||
*buf = (pd->msg->addr & 0x7f) << 1;
|
||||
*buf |= (pd->msg->flags & I2C_M_RD) ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
*buf = pd->msg->buf[pd->pos];
|
||||
}
|
||||
}
|
||||
|
||||
static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd)
|
||||
{
|
||||
unsigned char data;
|
||||
|
||||
if (pd->pos == pd->msg->len)
|
||||
return 1;
|
||||
|
||||
sh_mobile_i2c_get_data(pd, &data);
|
||||
|
||||
if (sh_mobile_i2c_is_last_byte(pd))
|
||||
i2c_op(pd, OP_TX_STOP, data);
|
||||
else if (sh_mobile_i2c_is_first_byte(pd))
|
||||
i2c_op(pd, OP_TX_FIRST, data);
|
||||
else
|
||||
i2c_op(pd, OP_TX, data);
|
||||
|
||||
pd->pos++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd)
|
||||
{
|
||||
unsigned char data;
|
||||
int real_pos;
|
||||
|
||||
do {
|
||||
if (pd->pos <= -1) {
|
||||
sh_mobile_i2c_get_data(pd, &data);
|
||||
|
||||
if (sh_mobile_i2c_is_first_byte(pd))
|
||||
i2c_op(pd, OP_TX_FIRST, data);
|
||||
else
|
||||
i2c_op(pd, OP_TX, data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pd->pos == 0) {
|
||||
i2c_op(pd, OP_TX_TO_RX, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
real_pos = pd->pos - 2;
|
||||
|
||||
if (pd->pos == pd->msg->len) {
|
||||
if (real_pos < 0) {
|
||||
i2c_op(pd, OP_RX_STOP, 0);
|
||||
break;
|
||||
}
|
||||
data = i2c_op(pd, OP_RX_STOP_DATA, 0);
|
||||
} else
|
||||
data = i2c_op(pd, OP_RX, 0);
|
||||
|
||||
pd->msg->buf[real_pos] = data;
|
||||
} while (0);
|
||||
|
||||
pd->pos++;
|
||||
return pd->pos == (pd->msg->len + 2);
|
||||
}
|
||||
|
||||
static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct platform_device *dev = dev_id;
|
||||
struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
|
||||
struct i2c_msg *msg = pd->msg;
|
||||
unsigned char data, sr;
|
||||
int wakeup = 0;
|
||||
unsigned char sr;
|
||||
int wakeup;
|
||||
|
||||
sr = ioread8(ICSR(pd));
|
||||
pd->sr |= sr;
|
||||
pd->sr |= sr; /* remember state */
|
||||
|
||||
dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
|
||||
(msg->flags & I2C_M_RD) ? "read" : "write",
|
||||
pd->pos, msg->len);
|
||||
(pd->msg->flags & I2C_M_RD) ? "read" : "write",
|
||||
pd->pos, pd->msg->len);
|
||||
|
||||
if (sr & (ICSR_AL | ICSR_TACK)) {
|
||||
iowrite8(0, ICIC(pd)); /* disable interrupts */
|
||||
wakeup = 1;
|
||||
goto do_wakeup;
|
||||
}
|
||||
/* don't interrupt transaction - continue to issue stop */
|
||||
iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd));
|
||||
wakeup = 0;
|
||||
} else if (pd->msg->flags & I2C_M_RD)
|
||||
wakeup = sh_mobile_i2c_isr_rx(pd);
|
||||
else
|
||||
wakeup = sh_mobile_i2c_isr_tx(pd);
|
||||
|
||||
if (pd->pos == msg->len) {
|
||||
i2c_op(pd, OP_RX_ONLY, 0);
|
||||
wakeup = 1;
|
||||
goto do_wakeup;
|
||||
}
|
||||
if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */
|
||||
iowrite8(sr & ~ICSR_WAIT, ICSR(pd));
|
||||
|
||||
if (pd->pos == -1) {
|
||||
data = (msg->addr & 0x7f) << 1;
|
||||
data |= (msg->flags & I2C_M_RD) ? 1 : 0;
|
||||
} else
|
||||
data = msg->buf[pd->pos];
|
||||
|
||||
if ((pd->pos == -1) || !(msg->flags & I2C_M_RD)) {
|
||||
if (msg->flags & I2C_M_RD)
|
||||
i2c_op(pd, OP_TX_TO_RX, data);
|
||||
else if (pd->pos == (msg->len - 1)) {
|
||||
i2c_op(pd, OP_TX_STOP, data);
|
||||
wakeup = 1;
|
||||
} else
|
||||
i2c_op(pd, OP_TX_ONLY, data);
|
||||
} else {
|
||||
if (pd->pos == (msg->len - 1))
|
||||
data = i2c_op(pd, OP_RX_STOP, 0);
|
||||
else
|
||||
data = i2c_op(pd, OP_RX_ONLY, 0);
|
||||
|
||||
msg->buf[pd->pos] = data;
|
||||
}
|
||||
pd->pos++;
|
||||
|
||||
do_wakeup:
|
||||
if (wakeup) {
|
||||
pd->sr |= SW_DONE;
|
||||
wake_up(&pd->wait);
|
||||
@@ -219,6 +361,11 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
|
||||
|
||||
static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
|
||||
{
|
||||
if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) {
|
||||
dev_err(pd->dev, "Unsupported zero length i2c read\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Initialize channel registers */
|
||||
iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
|
||||
|
||||
@@ -233,9 +380,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
|
||||
pd->pos = -1;
|
||||
pd->sr = 0;
|
||||
|
||||
/* Enable all interrupts except wait */
|
||||
iowrite8(ioread8(ICIC(pd)) | ICIC_ALE | ICIC_TACKE | ICIC_DTEE,
|
||||
ICIC(pd));
|
||||
/* Enable all interrupts to begin with */
|
||||
iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -268,25 +414,18 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
|
||||
if (!k)
|
||||
dev_err(pd->dev, "Transfer request timed out\n");
|
||||
|
||||
retry_count = 10;
|
||||
retry_count = 1000;
|
||||
again:
|
||||
val = ioread8(ICSR(pd));
|
||||
|
||||
dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
|
||||
|
||||
if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
|
||||
err = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* the interrupt handler may wake us up before the
|
||||
* transfer is finished, so poll the hardware
|
||||
* until we're done.
|
||||
*/
|
||||
|
||||
if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) &&
|
||||
(val & ICSR_SDAM))) {
|
||||
msleep(1);
|
||||
if (val & ICSR_BUSY) {
|
||||
udelay(10);
|
||||
if (retry_count--)
|
||||
goto again;
|
||||
|
||||
@@ -294,6 +433,12 @@ again:
|
||||
dev_err(pd->dev, "Polling timed out\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* handle missing acknowledge and arbitration lost */
|
||||
if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
|
||||
err = -EIO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
deactivate_ch(pd);
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
}
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static const struct usb_device_id bcm5974_table [] = {
|
||||
static const struct usb_device_id bcm5974_table[] = {
|
||||
/* MacbookAir1.1 */
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
|
||||
@@ -105,7 +105,7 @@ struct tp_header {
|
||||
|
||||
/* trackpad finger structure */
|
||||
struct tp_finger {
|
||||
__le16 origin; /* left/right origin? */
|
||||
__le16 origin; /* zero when switching track finger */
|
||||
__le16 abs_x; /* absolute x coodinate */
|
||||
__le16 abs_y; /* absolute y coodinate */
|
||||
__le16 rel_x; /* relative x coodinate */
|
||||
@@ -159,6 +159,7 @@ struct bcm5974 {
|
||||
struct bt_data *bt_data; /* button transferred data */
|
||||
struct urb *tp_urb; /* trackpad usb request block */
|
||||
struct tp_data *tp_data; /* trackpad transferred data */
|
||||
int fingers; /* number of fingers on trackpad */
|
||||
};
|
||||
|
||||
/* logical dimensions */
|
||||
@@ -172,6 +173,10 @@ struct bcm5974 {
|
||||
#define SN_WIDTH 100 /* width signal-to-noise ratio */
|
||||
#define SN_COORD 250 /* coordinate signal-to-noise ratio */
|
||||
|
||||
/* pressure thresholds */
|
||||
#define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE)
|
||||
#define PRESSURE_HIGH (3 * PRESSURE_LOW)
|
||||
|
||||
/* device constants */
|
||||
static const struct bcm5974_config bcm5974_config_table[] = {
|
||||
{
|
||||
@@ -248,6 +253,7 @@ static void setup_events_to_report(struct input_dev *input_dev,
|
||||
0, cfg->y.dim, cfg->y.fuzz, 0);
|
||||
|
||||
__set_bit(EV_KEY, input_dev->evbit);
|
||||
__set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
|
||||
@@ -273,32 +279,66 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
||||
const struct tp_finger *f = dev->tp_data->finger;
|
||||
struct input_dev *input = dev->input;
|
||||
const int fingers = (size - 26) / 28;
|
||||
int p = 0, w, x, y, n = 0;
|
||||
int raw_p, raw_w, raw_x, raw_y;
|
||||
int ptest = 0, origin = 0, nmin = 0, nmax = 0;
|
||||
int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
|
||||
|
||||
if (size < 26 || (size - 26) % 28 != 0)
|
||||
return -EIO;
|
||||
|
||||
/* always track the first finger; when detached, start over */
|
||||
if (fingers) {
|
||||
p = raw2int(f->force_major);
|
||||
w = raw2int(f->size_major);
|
||||
x = raw2int(f->abs_x);
|
||||
y = raw2int(f->abs_y);
|
||||
n = p > 0 ? fingers : 0;
|
||||
raw_p = raw2int(f->force_major);
|
||||
raw_w = raw2int(f->size_major);
|
||||
raw_x = raw2int(f->abs_x);
|
||||
raw_y = raw2int(f->abs_y);
|
||||
|
||||
dprintk(9,
|
||||
"bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
|
||||
p, w, x, y, n);
|
||||
"bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
|
||||
raw_p, raw_w, raw_x, raw_y);
|
||||
|
||||
input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w));
|
||||
input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin));
|
||||
input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y));
|
||||
ptest = int2bound(&c->p, raw_p);
|
||||
origin = raw2int(f->origin);
|
||||
}
|
||||
|
||||
input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p));
|
||||
/* while tracking finger still valid, count all fingers */
|
||||
if (ptest > PRESSURE_LOW && origin) {
|
||||
abs_p = ptest;
|
||||
abs_w = int2bound(&c->w, raw_w);
|
||||
abs_x = int2bound(&c->x, raw_x - c->x.devmin);
|
||||
abs_y = int2bound(&c->y, c->y.devmax - raw_y);
|
||||
for (; f != dev->tp_data->finger + fingers; f++) {
|
||||
ptest = int2bound(&c->p, raw2int(f->force_major));
|
||||
if (ptest > PRESSURE_LOW)
|
||||
nmax++;
|
||||
if (ptest > PRESSURE_HIGH)
|
||||
nmin++;
|
||||
}
|
||||
}
|
||||
|
||||
input_report_key(input, BTN_TOOL_FINGER, n == 1);
|
||||
input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
|
||||
input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2);
|
||||
if (dev->fingers < nmin)
|
||||
dev->fingers = nmin;
|
||||
if (dev->fingers > nmax)
|
||||
dev->fingers = nmax;
|
||||
|
||||
input_report_key(input, BTN_TOUCH, dev->fingers > 0);
|
||||
input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
|
||||
input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
|
||||
input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
|
||||
|
||||
input_report_abs(input, ABS_PRESSURE, abs_p);
|
||||
input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
|
||||
|
||||
if (abs_p) {
|
||||
input_report_abs(input, ABS_X, abs_x);
|
||||
input_report_abs(input, ABS_Y, abs_y);
|
||||
|
||||
dprintk(8,
|
||||
"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
|
||||
"nmin: %d nmax: %d n: %d\n",
|
||||
abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
|
||||
|
||||
}
|
||||
|
||||
input_sync(input);
|
||||
|
||||
|
||||
@@ -305,7 +305,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
|
||||
.ident = "Lenovo 3000 n100",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1068,7 +1068,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
|
||||
{
|
||||
v4l2_std_id *id = arg;
|
||||
int found = 0;
|
||||
int i, err;
|
||||
int i;
|
||||
|
||||
DEB_EE(("VIDIOC_S_STD\n"));
|
||||
|
||||
@@ -1116,7 +1116,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
|
||||
case VIDIOC_OVERLAY:
|
||||
{
|
||||
int on = *(int *)arg;
|
||||
int err = 0;
|
||||
|
||||
DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
|
||||
if (on != 0) {
|
||||
@@ -1192,7 +1191,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
|
||||
case VIDIOCGMBUF:
|
||||
{
|
||||
struct video_mbuf *mbuf = arg;
|
||||
struct videobuf_queue *q;
|
||||
int i;
|
||||
|
||||
/* fixme: number of capture buffers and sizes for v4l apps */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
* Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
* Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
* Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
|
||||
|
||||
Copyright (C) 2008 MaxLinear
|
||||
Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
Copyright (C) 2006 Steven Toth <stoth@linuxtv.org>
|
||||
Functions:
|
||||
mxl5005s_reset()
|
||||
mxl5005s_writereg()
|
||||
@@ -3837,7 +3837,7 @@ static u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
|
||||
/* ----------------------------------------------------------------
|
||||
* Begin: Everything after here is new code to adapt the
|
||||
* proprietary Realtek driver into a Linux API tuner.
|
||||
* Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
|
||||
* Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
|
||||
*/
|
||||
static int mxl5005s_reset(struct dvb_frontend *fe)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user