summaryrefslogtreecommitdiff
path: root/arch/mips/cavium-octeon
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/cavium-octeon')
-rw-r--r--arch/mips/cavium-octeon/dma-octeon.c8
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-board.c6
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-util.c20
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c14
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper.c17
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-pko.c149
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c38
-rw-r--r--arch/mips/cavium-octeon/setup.c2
8 files changed, 217 insertions, 37 deletions
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
index d8960d464..2cd45f5f9 100644
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -161,9 +161,6 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
{
void *ret;
- if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
- return ret;
-
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
@@ -194,11 +191,6 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
static void octeon_dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
{
- int order = get_order(size);
-
- if (dma_release_from_coherent(dev, order, vaddr))
- return;
-
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
}
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
index 9eb0feef4..36e30d65b 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -195,6 +195,12 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
return 8;
else
return -1;
+ case CVMX_BOARD_TYPE_KONTRON_S1901:
+ if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT)
+ return 1;
+ else
+ return -1;
+
}
/* Some unknown board. Somebody forgot to update this function... */
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
index 453d7f664..b45b29757 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
@@ -95,9 +95,9 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work)
uint8_t *data_address;
uint8_t *end_of_data;
- cvmx_dprintf("Packet Length: %u\n", work->len);
- cvmx_dprintf(" Input Port: %u\n", work->ipprt);
- cvmx_dprintf(" QoS: %u\n", work->qos);
+ cvmx_dprintf("Packet Length: %u\n", work->word1.len);
+ cvmx_dprintf(" Input Port: %u\n", cvmx_wqe_get_port(work));
+ cvmx_dprintf(" QoS: %u\n", cvmx_wqe_get_qos(work));
cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs);
if (work->word2.s.bufs == 0) {
@@ -127,7 +127,7 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work)
}
} else
buffer_ptr = work->packet_ptr;
- remaining_bytes = work->len;
+ remaining_bytes = work->word1.len;
while (remaining_bytes) {
start_of_buffer =
@@ -382,6 +382,10 @@ int cvmx_helper_get_ipd_port(int interface, int port)
return port + 32;
case 3:
return port + 36;
+ case 4:
+ return port + 40;
+ case 5:
+ return port + 44;
}
return -1;
}
@@ -404,6 +408,10 @@ int cvmx_helper_get_interface_num(int ipd_port)
return 2;
else if (ipd_port < 40)
return 3;
+ else if (ipd_port < 44)
+ return 4;
+ else if (ipd_port < 48)
+ return 5;
else
cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD "
"port number\n");
@@ -428,6 +436,10 @@ int cvmx_helper_get_interface_index_num(int ipd_port)
return ipd_port & 3;
else if (ipd_port < 40)
return ipd_port & 3;
+ else if (ipd_port < 44)
+ return ipd_port & 3;
+ else if (ipd_port < 48)
+ return ipd_port & 3;
else
cvmx_dprintf("cvmx_helper_get_interface_index_num: "
"Illegal IPD port number\n");
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
index 7653b7e92..a56ee590d 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
@@ -124,6 +124,13 @@ int __cvmx_helper_xaui_enable(int interface)
union cvmx_gmxx_tx_int_en gmx_tx_int_en;
union cvmx_pcsxx_int_en_reg pcsx_int_en_reg;
+ /* Setup PKND */
+ if (octeon_has_feature(OCTEON_FEATURE_PKND)) {
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
+ gmx_cfg.s.pknd = cvmx_helper_get_ipd_port(interface, 0);
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
+ }
+
/* (1) Interface has already been enabled. */
/* (2) Disable GMX. */
@@ -151,7 +158,12 @@ int __cvmx_helper_xaui_enable(int interface)
/* (4)c Aply reset sequence */
xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
xauiCtl.s.lo_pwr = 0;
- xauiCtl.s.reset = 1;
+
+ /* Issuing a reset here seems to hang some CN68XX chips. */
+ if (!OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) &&
+ !OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X))
+ xauiCtl.s.reset = 1;
+
cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
/* Wait for PCS to come out of reset */
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c
index 7e5cf7a5e..376701f41 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c
@@ -83,6 +83,8 @@ static cvmx_helper_link_info_t
*/
int cvmx_helper_get_number_of_interfaces(void)
{
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ return 9;
if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
return 4;
else
@@ -656,6 +658,21 @@ static int __cvmx_helper_global_setup_pko(void)
fau_to.s.tout_val = 0xfff;
fau_to.s.tout_enb = 0;
cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
+
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ union cvmx_pko_reg_min_pkt min_pkt;
+
+ min_pkt.u64 = 0;
+ min_pkt.s.size1 = 59;
+ min_pkt.s.size2 = 59;
+ min_pkt.s.size3 = 59;
+ min_pkt.s.size4 = 59;
+ min_pkt.s.size5 = 59;
+ min_pkt.s.size6 = 59;
+ min_pkt.s.size7 = 59;
+ cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
+ }
+
return 0;
}
diff --git a/arch/mips/cavium-octeon/executive/cvmx-pko.c b/arch/mips/cavium-octeon/executive/cvmx-pko.c
index 008b881cd..87be167a7 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-pko.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-pko.c
@@ -39,6 +39,143 @@
* Internal state of packet output
*/
+static int __cvmx_pko_int(int interface, int index)
+{
+ switch (interface) {
+ case 0:
+ return index;
+ case 1:
+ return 4;
+ case 2:
+ return index + 0x08;
+ case 3:
+ return index + 0x0c;
+ case 4:
+ return index + 0x10;
+ case 5:
+ return 0x1c;
+ case 6:
+ return 0x1d;
+ case 7:
+ return 0x1e;
+ case 8:
+ return 0x1f;
+ default:
+ return -1;
+ }
+}
+
+static void __cvmx_pko_iport_config(int pko_port)
+{
+ int queue;
+ const int num_queues = 1;
+ const int base_queue = pko_port;
+ const int static_priority_end = 1;
+ const int static_priority_base = 1;
+
+ for (queue = 0; queue < num_queues; queue++) {
+ union cvmx_pko_mem_iqueue_ptrs config;
+ cvmx_cmd_queue_result_t cmd_res;
+ uint64_t *buf_ptr;
+
+ config.u64 = 0;
+ config.s.index = queue;
+ config.s.qid = base_queue + queue;
+ config.s.ipid = pko_port;
+ config.s.tail = (queue == (num_queues - 1));
+ config.s.s_tail = (queue == static_priority_end);
+ config.s.static_p = (static_priority_base >= 0);
+ config.s.static_q = (queue <= static_priority_end);
+ config.s.qos_mask = 0xff;
+
+ cmd_res = cvmx_cmd_queue_initialize(
+ CVMX_CMD_QUEUE_PKO(base_queue + queue),
+ CVMX_PKO_MAX_QUEUE_DEPTH,
+ CVMX_FPA_OUTPUT_BUFFER_POOL,
+ (CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE -
+ CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST * 8));
+
+ WARN(cmd_res,
+ "%s: cmd_res=%d pko_port=%d base_queue=%d num_queues=%d queue=%d\n",
+ __func__, (int)cmd_res, pko_port, base_queue,
+ num_queues, queue);
+
+ buf_ptr = (uint64_t *)cvmx_cmd_queue_buffer(
+ CVMX_CMD_QUEUE_PKO(base_queue + queue));
+ config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr) >> 7;
+ CVMX_SYNCWS;
+ cvmx_write_csr(CVMX_PKO_MEM_IQUEUE_PTRS, config.u64);
+ }
+}
+
+static void __cvmx_pko_queue_alloc_o68(void)
+{
+ int port;
+
+ for (port = 0; port < 48; port++)
+ __cvmx_pko_iport_config(port);
+}
+
+static void __cvmx_pko_port_map_o68(void)
+{
+ int port;
+ int interface, index;
+ cvmx_helper_interface_mode_t mode;
+ union cvmx_pko_mem_iport_ptrs config;
+
+ /*
+ * Initialize every iport with the invalid eid.
+ */
+ config.u64 = 0;
+ config.s.eid = 31; /* Invalid */
+ for (port = 0; port < 128; port++) {
+ config.s.ipid = port;
+ cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64);
+ }
+
+ /*
+ * Set up PKO_MEM_IPORT_PTRS
+ */
+ for (port = 0; port < 48; port++) {
+ interface = cvmx_helper_get_interface_num(port);
+ index = cvmx_helper_get_interface_index_num(port);
+ mode = cvmx_helper_interface_get_mode(interface);
+ if (mode == CVMX_HELPER_INTERFACE_MODE_DISABLED)
+ continue;
+
+ config.s.ipid = port;
+ config.s.qos_mask = 0xff;
+ config.s.crc = 1;
+ config.s.min_pkt = 1;
+ config.s.intr = __cvmx_pko_int(interface, index);
+ config.s.eid = config.s.intr;
+ config.s.pipe = (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) ?
+ index : port;
+ cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64);
+ }
+}
+
+static void __cvmx_pko_chip_init(void)
+{
+ int i;
+
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ __cvmx_pko_port_map_o68();
+ __cvmx_pko_queue_alloc_o68();
+ return;
+ }
+
+ /*
+ * Initialize queues
+ */
+ for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) {
+ const uint64_t priority = 8;
+
+ cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1,
+ &priority);
+ }
+}
+
/**
* Call before any other calls to initialize the packet
* output system. This does chip global config, and should only be
@@ -47,8 +184,6 @@
void cvmx_pko_initialize_global(void)
{
- int i;
- uint64_t priority = 8;
union cvmx_pko_reg_cmd_buf config;
/*
@@ -62,9 +197,10 @@ void cvmx_pko_initialize_global(void)
cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64);
- for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++)
- cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1,
- &priority);
+ /*
+ * Chip-specific setup.
+ */
+ __cvmx_pko_chip_init();
/*
* If we aren't using all of the queues optimize PKO's
@@ -212,6 +348,9 @@ cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue,
int static_priority_base = -1;
int static_priority_end = -1;
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ return CVMX_PKO_SUCCESS;
+
if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS)
&& (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) {
cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n",
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index d8124a3c5..0352bc8d5 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -225,13 +225,14 @@ static int next_cpu_for_irq(struct irq_data *data)
#ifdef CONFIG_SMP
int cpu;
- int weight = cpumask_weight(data->affinity);
+ struct cpumask *mask = irq_data_get_affinity_mask(data);
+ int weight = cpumask_weight(mask);
struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data);
if (weight > 1) {
cpu = cd->current_cpu;
for (;;) {
- cpu = cpumask_next(cpu, data->affinity);
+ cpu = cpumask_next(cpu, mask);
if (cpu >= nr_cpu_ids) {
cpu = -1;
continue;
@@ -240,7 +241,7 @@ static int next_cpu_for_irq(struct irq_data *data)
}
}
} else if (weight == 1) {
- cpu = cpumask_first(data->affinity);
+ cpu = cpumask_first(mask);
} else {
cpu = smp_processor_id();
}
@@ -662,6 +663,11 @@ static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t)
irqd_set_trigger_type(data, t);
octeon_irq_gpio_setup(data);
+ if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH)
+ irq_set_handler_locked(data, handle_edge_irq);
+ else
+ irq_set_handler_locked(data, handle_level_irq);
+
return IRQ_SET_MASK_OK;
}
@@ -696,32 +702,23 @@ static void octeon_irq_ciu_gpio_ack(struct irq_data *data)
cvmx_write_csr(CVMX_GPIO_INT_CLR, mask);
}
-static void octeon_irq_handle_trigger(unsigned int irq, struct irq_desc *desc)
-{
- struct irq_data *data = irq_desc_get_irq_data(desc);
-
- if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH)
- handle_edge_irq(irq, desc);
- else
- handle_level_irq(irq, desc);
-}
-
#ifdef CONFIG_SMP
static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
{
int cpu = smp_processor_id();
cpumask_t new_affinity;
+ struct cpumask *mask = irq_data_get_affinity_mask(data);
- if (!cpumask_test_cpu(cpu, data->affinity))
+ if (!cpumask_test_cpu(cpu, mask))
return;
- if (cpumask_weight(data->affinity) > 1) {
+ if (cpumask_weight(mask) > 1) {
/*
* It has multi CPU affinity, just remove this CPU
* from the affinity set.
*/
- cpumask_copy(&new_affinity, data->affinity);
+ cpumask_copy(&new_affinity, mask);
cpumask_clear_cpu(cpu, &new_affinity);
} else {
/* Otherwise, put it on lowest numbered online CPU. */
@@ -1227,8 +1224,13 @@ static int octeon_irq_gpio_map(struct irq_domain *d,
octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL;
+ /*
+ * Default to handle_level_irq. If the DT contains a different
+ * trigger type, it will call the irq_set_type callback and
+ * the handler gets updated.
+ */
r = octeon_irq_set_ciu_mapping(virq, line, bit, hw,
- octeon_irq_gpio_chip, octeon_irq_handle_trigger);
+ octeon_irq_gpio_chip, handle_level_irq);
return r;
}
@@ -2219,7 +2221,7 @@ static irqreturn_t octeon_irq_cib_handler(int my_irq, void *data)
if (irqd_get_trigger_type(irq_data) &
IRQ_TYPE_EDGE_BOTH)
cvmx_write_csr(host_data->raw_reg, 1ull << i);
- generic_handle_irq_desc(irq, desc);
+ generic_handle_irq_desc(desc);
}
}
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 89a628455..bd634259e 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -933,7 +933,7 @@ void __init plat_mem_setup(void)
while ((boot_mem_map.nr_map < BOOT_MEM_MAP_MAX)
&& (total < MAX_MEMORY)) {
memory = cvmx_bootmem_phy_alloc(mem_alloc_size,
- __pa_symbol(&__init_end), -1,
+ __pa_symbol(&_end), -1,
0x100000,
CVMX_BOOTMEM_FLAG_NO_LOCKING);
if (memory >= 0) {