Commit 2432cbe4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus

Pull MIPS fixes from Ralf Baechle:
 "Random fixes across the MIPS tree.  The two hotspots are several bugs
  in the module loader and the ath79 SOC support; also noteworthy is the
  restructuring of the code to synchronize CPU timers across CPUs on
  startup; the old code recently ceased to work due to unrelated
  changes.

  All except one of these patches have sat for a significant time in
  linux-next for testing."

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus:
  MIPS: pci-ar724x: avoid data bus error due to a missing PCIe module
  MIPS: Malta: Delete duplicate PCI fixup.
  MIPS: ath79: don't hardcode the unavailability of the DSP ASE
  MIPS: Synchronize MIPS count one CPU at a time
  MIPS: BCM63xx: Fix SPI message control register handling for BCM6338/6348.
  MIPS: Module: Deal with malformed HI16/LO16 relocation sequences.
  MIPS: Fix race condition in module relocation code.
  MIPS: Fix memory leak in error path of HI16/LO16 relocation handling.
  MIPS: MTX-1: Add udelay to mtx1_pci_idsel
  MIPS: ath79: select HAVE_CLK
  MIPS: ath79: Use correct IRQ number for the OHCI controller on AR7240
  MIPS: ath79: Fix number of GPIO lines for AR724[12]
  MIPS: Octeon: Fix broken interrupt controller code.
parents 8497ae61 a1dca315
...@@ -89,6 +89,7 @@ config ATH79 ...@@ -89,6 +89,7 @@ config ATH79
select CEVT_R4K select CEVT_R4K
select CSRC_R4K select CSRC_R4K
select DMA_NONCOHERENT select DMA_NONCOHERENT
select HAVE_CLK
select IRQ_CPU select IRQ_CPU
select MIPS_MACHINE select MIPS_MACHINE
select SYS_HAS_CPU_MIPS32_R2 select SYS_HAS_CPU_MIPS32_R2
......
...@@ -228,6 +228,8 @@ static int mtx1_pci_idsel(unsigned int devsel, int assert) ...@@ -228,6 +228,8 @@ static int mtx1_pci_idsel(unsigned int devsel, int assert)
* adapter on the mtx-1 "singleboard" variant. It triggers a custom * adapter on the mtx-1 "singleboard" variant. It triggers a custom
* logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals. * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals.
*/ */
udelay(1);
if (assert && devsel != 0) if (assert && devsel != 0)
/* Suppress signal to Cardbus */ /* Suppress signal to Cardbus */
alchemy_gpio_set_value(1, 0); /* set EXT_IO3 OFF */ alchemy_gpio_set_value(1, 0); /* set EXT_IO3 OFF */
......
...@@ -145,6 +145,8 @@ static void __init ar7240_usb_setup(void) ...@@ -145,6 +145,8 @@ static void __init ar7240_usb_setup(void)
ath79_ohci_resources[0].start = AR7240_OHCI_BASE; ath79_ohci_resources[0].start = AR7240_OHCI_BASE;
ath79_ohci_resources[0].end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1; ath79_ohci_resources[0].end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1;
ath79_ohci_resources[1].start = ATH79_CPU_IRQ_USB;
ath79_ohci_resources[1].end = ATH79_CPU_IRQ_USB;
platform_device_register(&ath79_ohci_device); platform_device_register(&ath79_ohci_device);
} }
......
...@@ -188,8 +188,10 @@ void __init ath79_gpio_init(void) ...@@ -188,8 +188,10 @@ void __init ath79_gpio_init(void)
if (soc_is_ar71xx()) if (soc_is_ar71xx())
ath79_gpio_count = AR71XX_GPIO_COUNT; ath79_gpio_count = AR71XX_GPIO_COUNT;
else if (soc_is_ar724x()) else if (soc_is_ar7240())
ath79_gpio_count = AR724X_GPIO_COUNT; ath79_gpio_count = AR7240_GPIO_COUNT;
else if (soc_is_ar7241() || soc_is_ar7242())
ath79_gpio_count = AR7241_GPIO_COUNT;
else if (soc_is_ar913x()) else if (soc_is_ar913x())
ath79_gpio_count = AR913X_GPIO_COUNT; ath79_gpio_count = AR913X_GPIO_COUNT;
else if (soc_is_ar933x()) else if (soc_is_ar933x())
......
...@@ -106,11 +106,15 @@ int __init bcm63xx_spi_register(void) ...@@ -106,11 +106,15 @@ int __init bcm63xx_spi_register(void)
if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1; spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1;
spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE; spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE;
spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT;
spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH;
} }
if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
} }
bcm63xx_spi_regs_init(); bcm63xx_spi_regs_init();
......
...@@ -61,6 +61,12 @@ static void octeon_irq_set_ciu_mapping(int irq, int line, int bit, ...@@ -61,6 +61,12 @@ static void octeon_irq_set_ciu_mapping(int irq, int line, int bit,
octeon_irq_ciu_to_irq[line][bit] = irq; octeon_irq_ciu_to_irq[line][bit] = irq;
} }
static void octeon_irq_force_ciu_mapping(struct irq_domain *domain,
int irq, int line, int bit)
{
irq_domain_associate(domain, irq, line << 6 | bit);
}
static int octeon_coreid_for_cpu(int cpu) static int octeon_coreid_for_cpu(int cpu)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -183,19 +189,9 @@ static void __init octeon_irq_init_core(void) ...@@ -183,19 +189,9 @@ static void __init octeon_irq_init_core(void)
mutex_init(&cd->core_irq_mutex); mutex_init(&cd->core_irq_mutex);
irq = OCTEON_IRQ_SW0 + i; irq = OCTEON_IRQ_SW0 + i;
switch (irq) { irq_set_chip_data(irq, cd);
case OCTEON_IRQ_TIMER: irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
case OCTEON_IRQ_SW0: handle_percpu_irq);
case OCTEON_IRQ_SW1:
case OCTEON_IRQ_5:
case OCTEON_IRQ_PERF:
irq_set_chip_data(irq, cd);
irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
handle_percpu_irq);
break;
default:
break;
}
} }
} }
...@@ -890,7 +886,6 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d, ...@@ -890,7 +886,6 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
unsigned int type; unsigned int type;
unsigned int pin; unsigned int pin;
unsigned int trigger; unsigned int trigger;
struct octeon_irq_gpio_domain_data *gpiod;
if (d->of_node != node) if (d->of_node != node)
return -EINVAL; return -EINVAL;
...@@ -925,8 +920,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d, ...@@ -925,8 +920,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
break; break;
} }
*out_type = type; *out_type = type;
gpiod = d->host_data; *out_hwirq = pin;
*out_hwirq = gpiod->base_hwirq + pin;
return 0; return 0;
} }
...@@ -996,19 +990,21 @@ static int octeon_irq_ciu_map(struct irq_domain *d, ...@@ -996,19 +990,21 @@ static int octeon_irq_ciu_map(struct irq_domain *d,
static int octeon_irq_gpio_map(struct irq_domain *d, static int octeon_irq_gpio_map(struct irq_domain *d,
unsigned int virq, irq_hw_number_t hw) unsigned int virq, irq_hw_number_t hw)
{ {
unsigned int line = hw >> 6; struct octeon_irq_gpio_domain_data *gpiod = d->host_data;
unsigned int bit = hw & 63; unsigned int line, bit;
if (!octeon_irq_virq_in_range(virq)) if (!octeon_irq_virq_in_range(virq))
return -EINVAL; return -EINVAL;
hw += gpiod->base_hwirq;
line = hw >> 6;
bit = hw & 63;
if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0) if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL; return -EINVAL;
octeon_irq_set_ciu_mapping(virq, line, bit, octeon_irq_set_ciu_mapping(virq, line, bit,
octeon_irq_gpio_chip, octeon_irq_gpio_chip,
octeon_irq_handle_gpio); octeon_irq_handle_gpio);
return 0; return 0;
} }
...@@ -1149,6 +1145,7 @@ static void __init octeon_irq_init_ciu(void) ...@@ -1149,6 +1145,7 @@ static void __init octeon_irq_init_ciu(void)
struct irq_chip *chip_wd; struct irq_chip *chip_wd;
struct device_node *gpio_node; struct device_node *gpio_node;
struct device_node *ciu_node; struct device_node *ciu_node;
struct irq_domain *ciu_domain = NULL;
octeon_irq_init_ciu_percpu(); octeon_irq_init_ciu_percpu();
octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
...@@ -1177,31 +1174,6 @@ static void __init octeon_irq_init_ciu(void) ...@@ -1177,31 +1174,6 @@ static void __init octeon_irq_init_ciu(void)
/* Mips internal */ /* Mips internal */
octeon_irq_init_core(); octeon_irq_init_core();
/* CIU_0 */
for (i = 0; i < 16; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
for (i = 0; i < 4; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
for (i = 0; i < 4; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
for (i = 0; i < 4; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
/* CIU_1 */
for (i = 0; i < 16; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio"); gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
if (gpio_node) { if (gpio_node) {
struct octeon_irq_gpio_domain_data *gpiod; struct octeon_irq_gpio_domain_data *gpiod;
...@@ -1219,10 +1191,35 @@ static void __init octeon_irq_init_ciu(void) ...@@ -1219,10 +1191,35 @@ static void __init octeon_irq_init_ciu(void)
ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu"); ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
if (ciu_node) { if (ciu_node) {
irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL); ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
of_node_put(ciu_node); of_node_put(ciu_node);
} else } else
pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n"); panic("Cannot find device node for cavium,octeon-3860-ciu.");
/* CIU_0 */
for (i = 0; i < 16; i++)
octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_WORKQ0, 0, i + 0);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
for (i = 0; i < 4; i++)
octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_INT0, 0, i + 36);
for (i = 0; i < 4; i++)
octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 0, i + 40);
octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_RML, 0, 46);
for (i = 0; i < 4; i++)
octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52);
octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56);
octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_BOOTDMA, 0, 63);
/* CIU_1 */
for (i = 0; i < 16; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB1, 1, 17);
/* Enable the CIU lines */ /* Enable the CIU lines */
set_c0_status(STATUSF_IP3 | STATUSF_IP2); set_c0_status(STATUSF_IP3 | STATUSF_IP2);
......
...@@ -393,7 +393,8 @@ ...@@ -393,7 +393,8 @@
#define AR71XX_GPIO_REG_FUNC 0x28 #define AR71XX_GPIO_REG_FUNC 0x28
#define AR71XX_GPIO_COUNT 16 #define AR71XX_GPIO_COUNT 16
#define AR724X_GPIO_COUNT 18 #define AR7240_GPIO_COUNT 18
#define AR7241_GPIO_COUNT 20
#define AR913X_GPIO_COUNT 22 #define AR913X_GPIO_COUNT 22
#define AR933X_GPIO_COUNT 30 #define AR933X_GPIO_COUNT 30
#define AR934X_GPIO_COUNT 23 #define AR934X_GPIO_COUNT 23
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#define cpu_has_mips64r1 0 #define cpu_has_mips64r1 0
#define cpu_has_mips64r2 0 #define cpu_has_mips64r2 0
#define cpu_has_dsp 0
#define cpu_has_mipsmt 0 #define cpu_has_mipsmt 0
#define cpu_has_64bits 0 #define cpu_has_64bits 0
......
...@@ -9,6 +9,8 @@ int __init bcm63xx_spi_register(void); ...@@ -9,6 +9,8 @@ int __init bcm63xx_spi_register(void);
struct bcm63xx_spi_pdata { struct bcm63xx_spi_pdata {
unsigned int fifo_size; unsigned int fifo_size;
unsigned int msg_type_shift;
unsigned int msg_ctl_width;
int bus_num; int bus_num;
int num_chipselect; int num_chipselect;
u32 speed_hz; u32 speed_hz;
......
...@@ -1054,7 +1054,8 @@ ...@@ -1054,7 +1054,8 @@
#define SPI_6338_FILL_BYTE 0x07 #define SPI_6338_FILL_BYTE 0x07
#define SPI_6338_MSG_TAIL 0x09 #define SPI_6338_MSG_TAIL 0x09
#define SPI_6338_RX_TAIL 0x0b #define SPI_6338_RX_TAIL 0x0b
#define SPI_6338_MSG_CTL 0x40 #define SPI_6338_MSG_CTL 0x40 /* 8-bits register */
#define SPI_6338_MSG_CTL_WIDTH 8
#define SPI_6338_MSG_DATA 0x41 #define SPI_6338_MSG_DATA 0x41
#define SPI_6338_MSG_DATA_SIZE 0x3f #define SPI_6338_MSG_DATA_SIZE 0x3f
#define SPI_6338_RX_DATA 0x80 #define SPI_6338_RX_DATA 0x80
...@@ -1070,7 +1071,8 @@ ...@@ -1070,7 +1071,8 @@
#define SPI_6348_FILL_BYTE 0x07 #define SPI_6348_FILL_BYTE 0x07
#define SPI_6348_MSG_TAIL 0x09 #define SPI_6348_MSG_TAIL 0x09
#define SPI_6348_RX_TAIL 0x0b #define SPI_6348_RX_TAIL 0x0b
#define SPI_6348_MSG_CTL 0x40 #define SPI_6348_MSG_CTL 0x40 /* 8-bits register */
#define SPI_6348_MSG_CTL_WIDTH 8
#define SPI_6348_MSG_DATA 0x41 #define SPI_6348_MSG_DATA 0x41
#define SPI_6348_MSG_DATA_SIZE 0x3f #define SPI_6348_MSG_DATA_SIZE 0x3f
#define SPI_6348_RX_DATA 0x80 #define SPI_6348_RX_DATA 0x80
...@@ -1078,6 +1080,7 @@ ...@@ -1078,6 +1080,7 @@
/* BCM 6358 SPI core */ /* BCM 6358 SPI core */
#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */ #define SPI_6358_MSG_CTL 0x00 /* 16-bits register */
#define SPI_6358_MSG_CTL_WIDTH 16
#define SPI_6358_MSG_DATA 0x02 #define SPI_6358_MSG_DATA 0x02
#define SPI_6358_MSG_DATA_SIZE 0x21e #define SPI_6358_MSG_DATA_SIZE 0x21e
#define SPI_6358_RX_DATA 0x400 #define SPI_6358_RX_DATA 0x400
...@@ -1094,6 +1097,7 @@ ...@@ -1094,6 +1097,7 @@
/* BCM 6358 SPI core */ /* BCM 6358 SPI core */
#define SPI_6368_MSG_CTL 0x00 /* 16-bits register */ #define SPI_6368_MSG_CTL 0x00 /* 16-bits register */
#define SPI_6368_MSG_CTL_WIDTH 16
#define SPI_6368_MSG_DATA 0x02 #define SPI_6368_MSG_DATA 0x02
#define SPI_6368_MSG_DATA_SIZE 0x21e #define SPI_6368_MSG_DATA_SIZE 0x21e
#define SPI_6368_RX_DATA 0x400 #define SPI_6368_RX_DATA 0x400
...@@ -1115,7 +1119,10 @@ ...@@ -1115,7 +1119,10 @@
#define SPI_HD_W 0x01 #define SPI_HD_W 0x01
#define SPI_HD_R 0x02 #define SPI_HD_R 0x02
#define SPI_BYTE_CNT_SHIFT 0 #define SPI_BYTE_CNT_SHIFT 0
#define SPI_MSG_TYPE_SHIFT 14 #define SPI_6338_MSG_TYPE_SHIFT 6
#define SPI_6348_MSG_TYPE_SHIFT 6
#define SPI_6358_MSG_TYPE_SHIFT 14
#define SPI_6368_MSG_TYPE_SHIFT 14
/* Command */ /* Command */
#define SPI_CMD_NOOP 0x00 #define SPI_CMD_NOOP 0x00
......
...@@ -21,14 +21,10 @@ enum octeon_irq { ...@@ -21,14 +21,10 @@ enum octeon_irq {
OCTEON_IRQ_TIMER, OCTEON_IRQ_TIMER,
/* sources in CIU_INTX_EN0 */ /* sources in CIU_INTX_EN0 */
OCTEON_IRQ_WORKQ0, OCTEON_IRQ_WORKQ0,
OCTEON_IRQ_GPIO0 = OCTEON_IRQ_WORKQ0 + 16, OCTEON_IRQ_WDOG0 = OCTEON_IRQ_WORKQ0 + 16,
OCTEON_IRQ_WDOG0 = OCTEON_IRQ_GPIO0 + 16,
OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15, OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15,
OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16, OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16,
OCTEON_IRQ_MBOX1, OCTEON_IRQ_MBOX1,
OCTEON_IRQ_UART0,
OCTEON_IRQ_UART1,
OCTEON_IRQ_UART2,
OCTEON_IRQ_PCI_INT0, OCTEON_IRQ_PCI_INT0,
OCTEON_IRQ_PCI_INT1, OCTEON_IRQ_PCI_INT1,
OCTEON_IRQ_PCI_INT2, OCTEON_IRQ_PCI_INT2,
...@@ -38,8 +34,6 @@ enum octeon_irq { ...@@ -38,8 +34,6 @@ enum octeon_irq {
OCTEON_IRQ_PCI_MSI2, OCTEON_IRQ_PCI_MSI2,
OCTEON_IRQ_PCI_MSI3, OCTEON_IRQ_PCI_MSI3,
OCTEON_IRQ_TWSI,
OCTEON_IRQ_TWSI2,
OCTEON_IRQ_RML, OCTEON_IRQ_RML,
OCTEON_IRQ_TIMER0, OCTEON_IRQ_TIMER0,
OCTEON_IRQ_TIMER1, OCTEON_IRQ_TIMER1,
...@@ -47,8 +41,6 @@ enum octeon_irq { ...@@ -47,8 +41,6 @@ enum octeon_irq {
OCTEON_IRQ_TIMER3, OCTEON_IRQ_TIMER3,
OCTEON_IRQ_USB0, OCTEON_IRQ_USB0,
OCTEON_IRQ_USB1, OCTEON_IRQ_USB1,
OCTEON_IRQ_MII0,
OCTEON_IRQ_MII1,
OCTEON_IRQ_BOOTDMA, OCTEON_IRQ_BOOTDMA,
#ifndef CONFIG_PCI_MSI #ifndef CONFIG_PCI_MSI
OCTEON_IRQ_LAST = 127 OCTEON_IRQ_LAST = 127
......
...@@ -10,6 +10,7 @@ struct mod_arch_specific { ...@@ -10,6 +10,7 @@ struct mod_arch_specific {
struct list_head dbe_list; struct list_head dbe_list;
const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_start;
const struct exception_table_entry *dbe_end; const struct exception_table_entry *dbe_end;
struct mips_hi16 *r_mips_hi16_list;
}; };
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
......
...@@ -12,16 +12,16 @@ ...@@ -12,16 +12,16 @@
#ifdef CONFIG_SYNC_R4K #ifdef CONFIG_SYNC_R4K
extern void synchronise_count_master(void); extern void synchronise_count_master(int cpu);
extern void synchronise_count_slave(void); extern void synchronise_count_slave(int cpu);
#else #else
static inline void synchronise_count_master(void) static inline void synchronise_count_master(int cpu)
{ {
} }
static inline void synchronise_count_slave(void) static inline void synchronise_count_slave(int cpu)
{ {
} }
......
...@@ -39,8 +39,6 @@ struct mips_hi16 { ...@@ -39,8 +39,6 @@ struct mips_hi16 {
Elf_Addr value; Elf_Addr value;
}; };
static struct mips_hi16 *mips_hi16_list;
static LIST_HEAD(dbe_list); static LIST_HEAD(dbe_list);
static DEFINE_SPINLOCK(dbe_lock); static DEFINE_SPINLOCK(dbe_lock);
...@@ -128,8 +126,8 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) ...@@ -128,8 +126,8 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
n->addr = (Elf_Addr *)location; n->addr = (Elf_Addr *)location;
n->value = v; n->value = v;
n->next = mips_hi16_list; n->next = me->arch.r_mips_hi16_list;
mips_hi16_list = n; me->arch.r_mips_hi16_list = n;
return 0; return 0;
} }
...@@ -142,18 +140,28 @@ static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) ...@@ -142,18 +140,28 @@ static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v)
return 0; return 0;
} }
static void free_relocation_chain(struct mips_hi16 *l)
{
struct mips_hi16 *next;
while (l) {
next = l->next;
kfree(l);
l = next;
}
}
static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
{ {
unsigned long insnlo = *location; unsigned long insnlo = *location;
struct mips_hi16 *l;
Elf_Addr val, vallo; Elf_Addr val, vallo;
/* Sign extend the addend we extract from the lo insn. */ /* Sign extend the addend we extract from the lo insn. */
vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
if (mips_hi16_list != NULL) { if (me->arch.r_mips_hi16_list != NULL) {
struct mips_hi16 *l; l = me->arch.r_mips_hi16_list;
l = mips_hi16_list;
while (l != NULL) { while (l != NULL) {
struct mips_hi16 *next; struct mips_hi16 *next;
unsigned long insn; unsigned long insn;
...@@ -188,7 +196,7 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) ...@@ -188,7 +196,7 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
l = next; l = next;
} }
mips_hi16_list = NULL; me->arch.r_mips_hi16_list = NULL;
} }
/* /*
...@@ -201,6 +209,9 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) ...@@ -201,6 +209,9 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
return 0; return 0;
out_danger: out_danger:
free_relocation_chain(l);
me->arch.r_mips_hi16_list = NULL;
pr_err("module %s: dangerous R_MIPS_LO16 REL relocation\n", me->name); pr_err("module %s: dangerous R_MIPS_LO16 REL relocation\n", me->name);
return -ENOEXEC; return -ENOEXEC;
...@@ -273,6 +284,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, ...@@ -273,6 +284,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
pr_debug("Applying relocate section %u to %u\n", relsec, pr_debug("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info); sechdrs[relsec].sh_info);
me->arch.r_mips_hi16_list = NULL;
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */ /* This is where to make the change */
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
...@@ -296,6 +308,19 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, ...@@ -296,6 +308,19 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
return res; return res;
} }
/*
* Normally the hi16 list should be deallocated at this point. A
* malformed binary however could contain a series of R_MIPS_HI16
* relocations not followed by a R_MIPS_LO16 relocation. In that
* case, free up the list and return an error.
*/
if (me->arch.r_mips_hi16_list) {
free_relocation_chain(me->arch.r_mips_hi16_list);
me->arch.r_mips_hi16_list = NULL;
return -ENOEXEC;
}
return 0; return 0;
} }
......
...@@ -130,7 +130,7 @@ asmlinkage __cpuinit void start_secondary(void) ...@@ -130,7 +130,7 @@ asmlinkage __cpuinit void start_secondary(void)
cpu_set(cpu, cpu_callin_map); cpu_set(cpu, cpu_callin_map);
synchronise_count_slave(); synchronise_count_slave(cpu);
/* /*
* irq will be enabled in ->smp_finish(), enabling it too early * irq will be enabled in ->smp_finish(), enabling it too early
...@@ -173,7 +173,6 @@ void smp_send_stop(void) ...@@ -173,7 +173,6 @@ void smp_send_stop(void)
void __init smp_cpus_done(unsigned int max_cpus) void __init smp_cpus_done(unsigned int max_cpus)
{ {
mp_ops->cpus_done(); mp_ops->cpus_done();
synchronise_count_master();
} }
/* called from main before smp_init() */ /* called from main before smp_init() */
...@@ -206,6 +205,7 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) ...@@ -206,6 +205,7 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
while (!cpu_isset(cpu, cpu_callin_map)) while (!cpu_isset(cpu, cpu_callin_map))
udelay(100); udelay(100);
synchronise_count_master(cpu);
return 0; return 0;
} }
......
...@@ -28,12 +28,11 @@ static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0); ...@@ -28,12 +28,11 @@ static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0);
#define COUNTON 100 #define COUNTON 100
#define NR_LOOPS 5 #define NR_LOOPS 5
void __cpuinit synchronise_count_master(void) void __cpuinit synchronise_count_master(int cpu)
{ {
int i; int i;
unsigned long flags; unsigned long flags;
unsigned int initcount; unsigned int initcount;
int nslaves;
#ifdef CONFIG_MIPS_MT_SMTC #ifdef CONFIG_MIPS_MT_SMTC
/* /*
...@@ -43,8 +42,7 @@ void __cpuinit synchronise_count_master(void) ...@@ -43,8 +42,7 @@ void __cpuinit synchronise_count_master(void)
return; return;
#endif #endif
printk(KERN_INFO "Synchronize counters across %u CPUs: ", printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu);
num_online_cpus());
local_irq_save(flags); local_irq_save(flags);
...@@ -52,7 +50,7 @@ void __cpuinit synchronise_count_master(void) ...@@ -52,7 +50,7 @@ void __cpuinit synchronise_count_master(void)
* Notify the slaves that it's time to start * Notify the slaves that it's time to start
*/ */
atomic_set(&count_reference, read_c0_count()); atomic_set(&count_reference, read_c0_count());
atomic_set(&count_start_flag, 1); atomic_set(&count_start_flag, cpu);
smp_wmb(); smp_wmb();
/* Count will be initialised to current timer for all CPU's */ /* Count will be initialised to current timer for all CPU's */
...@@ -69,10 +67,9 @@ void __cpuinit synchronise_count_master(void) ...@@ -69,10 +67,9 @@ void __cpuinit synchronise_count_master(void)
* two CPUs. * two CPUs.
*/ */
nslaves = num_online_cpus()-1;
for (i = 0; i < NR_LOOPS; i++) { for (i = 0; i < NR_LOOPS; i++) {
/* slaves loop on '!= ncpus' */ /* slaves loop on '!= 2' */
while (atomic_read(&count_count_start) != nslaves) while (atomic_read(&count_count_start) != 1)
mb(); mb();
atomic_set(&count_count_stop, 0); atomic_set(&count_count_stop, 0);
smp_wmb(); smp_wmb();
...@@ -89,7 +86,7 @@ void __cpuinit synchronise_count_master(void) ...@@ -89,7 +86,7 @@ void __cpuinit synchronise_count_master(void)
/* /*
* Wait for all slaves to leave the synchronization point: * Wait for all slaves to leave the synchronization point:
*/ */
while (atomic_read(&count_count_stop) != nslaves) while (atomic_read(&count_count_stop) != 1)
mb(); mb();
atomic_set(&count_count_start, 0); atomic_set(&count_count_start, 0);
smp_wmb(); smp_wmb();
...@@ -97,6 +94,7 @@ void __cpuinit synchronise_count_master(void) ...@@ -97,6 +94,7 @@ void __cpuinit synchronise_count_master(void)
} }
/* Arrange for an interrupt in a short while */ /* Arrange for an interrupt in a short while */
write_c0_compare(read_c0_count() + COUNTON); write_c0_compare(read_c0_count() + COUNTON);
atomic_set(&count_start_flag, 0);
local_irq_restore(flags); local_irq_restore(flags);
...@@ -108,11 +106,10 @@ void __cpuinit synchronise_count_master(void) ...@@ -108,11 +106,10 @@ void __cpuinit synchronise_count_master(void)
printk("done.\n"); printk("done.\n");
} }
void __cpuinit synchronise_count_slave(void) void __cpuinit synchronise_count_slave(int cpu)
{ {
int i; int i;
unsigned int initcount; unsigned int initcount;
int ncpus;
#ifdef CONFIG_MIPS_MT_SMTC #ifdef CONFIG_MIPS_MT_SMTC
/* /*
...@@ -127,16 +124,15 @@ void __cpuinit synchronise_count_slave(void) ...@@ -127,16 +124,15 @@ void __cpuinit synchronise_count_slave(void)
* so we first wait for the master to say everyone is ready * so we first wait for the master to say everyone is ready
*/ */
while (!atomic_read(&count_start_flag)) while (atomic_read(&count_start_flag) != cpu)
mb(); mb();
/* Count will be initialised to next expire for all CPU's */ /* Count will be initialised to next expire for all CPU's */
initcount = atomic_read(&count_reference); initcount = atomic_read(&count_reference);
ncpus = num_online_cpus();
for (i = 0; i < NR_LOOPS; i++) { for (i = 0; i < NR_LOOPS; i++) {
atomic_inc(&count_count_start); atomic_inc(&count_count_start);
while (atomic_read(&count_count_start) != ncpus) while (atomic_read(&count_count_start) != 2)
mb(); mb();
/* /*
...@@ -146,7 +142,7 @@ void __cpuinit synchronise_count_slave(void) ...@@ -146,7 +142,7 @@ void __cpuinit synchronise_count_slave(void)
write_c0_count(initcount); write_c0_count(initcount);
atomic_inc(&count_count_stop); atomic_inc(&count_count_stop);
while (atomic_read(&count_count_stop) != ncpus) while (atomic_read(&count_count_stop) != 2)
mb(); mb();
} }
/* Arrange for an interrupt in a short while */ /* Arrange for an interrupt in a short while */
......
...@@ -252,16 +252,3 @@ void __init mips_pcibios_init(void) ...@@ -252,16 +252,3 @@ void __init mips_pcibios_init(void)
register_pci_controller(controller); register_pci_controller(controller);
} }
/* Enable PCI 2.1 compatibility in PIIX4 */
static void __devinit quirk_dlcsetup(struct pci_dev *dev)
{
u8 odlc, ndlc;
(void) pci_read_config_byte(dev, 0x82, &odlc);
/* Enable passive releases and delayed transaction */
ndlc = odlc | 7;
(void) pci_write_config_byte(dev, 0x82, ndlc);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
quirk_dlcsetup);
...@@ -23,9 +23,12 @@ ...@@ -23,9 +23,12 @@
#define AR724X_PCI_MEM_BASE 0x10000000 #define AR724X_PCI_MEM_BASE 0x10000000
#define AR724X_PCI_MEM_SIZE 0x08000000 #define AR724X_PCI_MEM_SIZE 0x08000000
#define AR724X_PCI_REG_RESET 0x18
#define AR724X_PCI_REG_INT_STATUS 0x4c #define AR724X_PCI_REG_INT_STATUS 0x4c
#define AR724X_PCI_REG_INT_MASK 0x50 #define AR724X_PCI_REG_INT_MASK 0x50
#define AR724X_PCI_RESET_LINK_UP BIT(0)
#define AR724X_PCI_INT_DEV0 BIT(14) #define AR724X_PCI_INT_DEV0 BIT(14)
#define AR724X_PCI_IRQ_COUNT 1 #define AR724X_PCI_IRQ_COUNT 1
...@@ -38,6 +41,15 @@ static void __iomem *ar724x_pci_ctrl_base; ...@@ -38,6 +41,15 @@ static void __iomem *ar724x_pci_ctrl_base;
static u32 ar724x_pci_bar0_value; static u32 ar724x_pci_bar0_value;
static bool ar724x_pci_bar0_is_cached; static bool ar724x_pci_bar0_is_cached;
static bool ar724x_pci_link_up;
static inline bool ar724x_pci_check_link(void)
{
u32 reset;
reset = __raw_readl(ar724x_pci_ctrl_base + AR724X_PCI_REG_RESET);
return reset & AR724X_PCI_RESET_LINK_UP;
}
static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, uint32_t *value) int size, uint32_t *value)
...@@ -46,6 +58,9 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -46,6 +58,9 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
void __iomem *base; void __iomem *base;
u32 data; u32 data;
if (!ar724x_pci_link_up)
return PCIBIOS_DEVICE_NOT_FOUND;
if (devfn) if (devfn)
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
...@@ -96,6 +111,9 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -96,6 +111,9 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
u32 data; u32 data;
int s; int s;
if (!ar724x_pci_link_up)
return PCIBIOS_DEVICE_NOT_FOUND;
if (devfn) if (devfn)
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
...@@ -280,6 +298,10 @@ int __init ar724x_pcibios_init(int irq) ...@@ -280,6 +298,10 @@ int __init ar724x_pcibios_init(int irq)
if (ar724x_pci_ctrl_base == NULL) if (ar724x_pci_ctrl_base == NULL)
goto err_unmap_devcfg; goto err_unmap_devcfg;
ar724x_pci_link_up = ar724x_pci_check_link();
if (!ar724x_pci_link_up)
pr_warn("ar724x: PCIe link is down\n");
ar724x_pci_irq_init(irq); ar724x_pci_irq_init(irq);
register_pci_controller(&ar724x_pci_controller); register_pci_controller(&ar724x_pci_controller);
......
...@@ -47,6 +47,8 @@ struct bcm63xx_spi { ...@@ -47,6 +47,8 @@ struct bcm63xx_spi {
/* Platform data */ /* Platform data */
u32 speed_hz; u32 speed_hz;
unsigned fifo_size; unsigned fifo_size;
unsigned int msg_type_shift;
unsigned int msg_ctl_width;
/* Data buffers */ /* Data buffers */
const unsigned char *tx_ptr; const unsigned char *tx_ptr;
...@@ -221,13 +223,20 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, ...@@ -221,13 +223,20 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
if (t->rx_buf && t->tx_buf) if (t->rx_buf && t->tx_buf)
msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT); msg_ctl |= (SPI_FD_RW << bs->msg_type_shift);
else if (t->rx_buf) else if (t->rx_buf)
msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT); msg_ctl |= (SPI_HD_R << bs->msg_type_shift);
else if (t->tx_buf) else if (t->tx_buf)
msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT); msg_ctl |= (SPI_HD_W << bs->msg_type_shift);
bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL); switch (bs->msg_ctl_width) {
case 8:
bcm_spi_writeb(bs, msg_ctl, SPI_MSG_CTL);
break;
case 16:
bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
break;
}
/* Issue the transfer */ /* Issue the transfer */
cmd = SPI_CMD_START_IMMEDIATE; cmd = SPI_CMD_START_IMMEDIATE;
...@@ -406,9 +415,21 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev) ...@@ -406,9 +415,21 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
master->transfer_one_message = bcm63xx_spi_transfer_one; master->transfer_one_message = bcm63xx_spi_transfer_one;
master->mode_bits = MODEBITS; master->mode_bits = MODEBITS;
bs->speed_hz = pdata->speed_hz; bs->speed_hz = pdata->speed_hz;
bs->msg_type_shift = pdata->msg_type_shift;
bs->msg_ctl_width = pdata->msg_ctl_width;
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
switch (bs->msg_ctl_width) {
case 8:
case 16:
break;
default:
dev_err(dev, "unsupported MSG_CTL width: %d\n",
bs->msg_ctl_width);
goto out_clk_disable;
}
/* Initialize hardware */ /* Initialize hardware */
clk_enable(bs->clk); clk_enable(bs->clk);
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment