mirror of
https://github.com/gnuton/asuswrt-merlin.ng.git
synced 2025-05-19 16:02:36 +02:00
181 lines
5.8 KiB
C
181 lines
5.8 KiB
C
/*
|
|
* <:copyright-BRCM:2013:DUAL/GPL:standard
|
|
*
|
|
* Copyright (c) 2013 Broadcom
|
|
* All Rights Reserved
|
|
*
|
|
* Unless you and Broadcom execute a separate written software license
|
|
* agreement governing use of this software, this software is licensed
|
|
* to you under the terms of the GNU General Public License version 2
|
|
* (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
|
|
* with the following added to such license:
|
|
*
|
|
* As a special exception, the copyright holders of this software give
|
|
* you permission to link this software with independent modules, and
|
|
* to copy and distribute the resulting executable under terms of your
|
|
* choice, provided that you also meet, for each linked independent
|
|
* module, the terms and conditions of the license of that module.
|
|
* An independent module is a module which is not derived from this
|
|
* software. The special exception does not apply to any modifications
|
|
* of the software.
|
|
*
|
|
* Not withstanding the above, under no circumstances may you combine
|
|
* this software in any way with any other Broadcom software provided
|
|
* under a license other than the GPL, without Broadcom's express prior
|
|
* written consent.
|
|
*
|
|
* :>
|
|
*/
|
|
// BCMFORMAT: notabs reindent:uncrustify:bcm_minimal_i4.cfg
|
|
|
|
/*
|
|
These are low level functions that can be called from CFE or from the Linux init code.
|
|
If pinmux changes are needed after Linux init, support should be added to the board
|
|
driver including any necessary locking.
|
|
*/
|
|
|
|
#include "boardparms.h"
|
|
#include "bcm_pinmux.h"
|
|
#include "bcm_led.h"
|
|
|
|
#ifdef _CFE_
|
|
#include "lib_types.h"
|
|
#include "lib_printf.h"
|
|
#include "lib_string.h"
|
|
#include "bcm_map.h"
|
|
#define printk printf
|
|
#else // Linux
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <bcm_map_part.h>
|
|
#include <linux/string.h>
|
|
#endif
|
|
|
|
void bcm_get_pinmux(unsigned int pin_num, unsigned int *mux_num)
|
|
{
|
|
unsigned int tp_blk_data_lsb;
|
|
tp_blk_data_lsb= 0;
|
|
tp_blk_data_lsb |= pin_num;
|
|
GPIO->TestPortBlockDataMSB = 0;
|
|
GPIO->TestPortBlockDataLSB = tp_blk_data_lsb;
|
|
GPIO->TestPortCmd = 0x23;
|
|
|
|
*mux_num = (GPIO->DiagReadBack >> PINMUX_DATA_SHIFT) & 0x7;
|
|
}
|
|
|
|
void bcm_set_pinmux(unsigned int pin_num, unsigned int mux_num)
|
|
{
|
|
unsigned int tp_blk_data_lsb;
|
|
//printk("set pinmux %d to %d\n",pin_num, mux_num);
|
|
|
|
tp_blk_data_lsb= 0;
|
|
tp_blk_data_lsb |= pin_num;
|
|
tp_blk_data_lsb |= (mux_num << PINMUX_DATA_SHIFT);
|
|
GPIO->TestPortBlockDataMSB = 0;
|
|
GPIO->TestPortBlockDataLSB = tp_blk_data_lsb;
|
|
GPIO->TestPortCmd = LOAD_MUX_REG_CMD;
|
|
}
|
|
|
|
void bcm_init_pinmux_interface(unsigned int interface) {
|
|
int i, n, errcnt;
|
|
unsigned short Function[BP_PINMUX_MAX];
|
|
unsigned int Muxinfo[BP_PINMUX_MAX];
|
|
|
|
if (BP_SUCCESS != BpGetIfacePinmux (interface, BP_PINMUX_MAX, &n, &errcnt, Function, Muxinfo)) {
|
|
return;
|
|
}
|
|
for (i = n-1 ; 0 <= i ; i--) {
|
|
bcm_set_pinmux( Muxinfo[i] & BP_PINMUX_PIN_MASK, (Muxinfo[i] & BP_PINMUX_VAL_MASK) >> BP_PINMUX_VAL_SHIFT );
|
|
}
|
|
}
|
|
|
|
int bcm_pinmux_update_optled_map(unsigned short led_gpio_num, unsigned int muxinfo)
|
|
{
|
|
short *optled_map;
|
|
int led_chn_num = led_gpio_num;
|
|
|
|
optled_map = bcm_led_driver_get_optled_map();
|
|
|
|
if (muxinfo & BP_PINMUX_OPTLED_VALID) {
|
|
led_chn_num = (muxinfo & BP_PINMUX_OPTLED_MASK) >> BP_PINMUX_OPTLED_SHIFT;
|
|
optled_map[led_gpio_num] = led_chn_num;
|
|
} else {
|
|
optled_map[led_gpio_num] = led_gpio_num;
|
|
}
|
|
|
|
return led_chn_num;
|
|
}
|
|
|
|
int bcm_init_pinmux(void)
|
|
{
|
|
int i, n, errcnt, op;
|
|
int lednum;
|
|
unsigned int serial = 0;
|
|
unsigned int ledsrc = 0;
|
|
unsigned short Function[BP_PINMUX_MAX];
|
|
unsigned int Muxinfo[BP_PINMUX_MAX];
|
|
|
|
if (BP_SUCCESS != BpGetAllPinmux (BP_PINMUX_MAX, &n, &errcnt, Function, Muxinfo)) {
|
|
return 0;
|
|
}
|
|
|
|
for (i = n-1 ; 0 <= i ; i--) {
|
|
lednum = Function[i] & BP_GPIO_NUM_MASK;
|
|
lednum = bcm_pinmux_update_optled_map(lednum, Muxinfo[i]);
|
|
op = Muxinfo[i] & BP_PINMUX_OP_MASK;
|
|
if (Function[i] & BP_GPIO_SERIAL) {
|
|
serial |= 1 << (Function[i] & BP_GPIO_NUM_MASK);
|
|
bcm_led_zero_flash_rate(Function[i] & BP_GPIO_NUM_MASK);
|
|
#if defined(CONFIG_BCM96855) || defined(_BCM96855_)
|
|
bcm_cled_mux_leds(Function[i] & BP_GPIO_NUM_MASK, Function[i] & BP_GPIO_NUM_MASK, lednum,
|
|
op == BP_PINMUX_HWLED);
|
|
#endif
|
|
} else {
|
|
bcm_set_pinmux( Muxinfo[i] & BP_PINMUX_PIN_MASK, (Muxinfo[i] & BP_PINMUX_VAL_MASK) >> BP_PINMUX_VAL_SHIFT );
|
|
if ((op == BP_PINMUX_HWLED) || (op == BP_PINMUX_SWLED)) {
|
|
// zero the flash rate for any LED that needs to be on/off
|
|
bcm_led_zero_flash_rate(lednum);
|
|
#if defined(CONFIG_BCM96855) || defined(_BCM96855_)
|
|
{
|
|
unsigned int led_src;
|
|
if (BP_SUCCESS == BpMapGpioToLed(Function[i] & BP_GPIO_NUM_MASK, &led_src))
|
|
{
|
|
bcm_cled_mux_leds(Function[i] & BP_GPIO_NUM_MASK, led_src, lednum,
|
|
op == BP_PINMUX_HWLED);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
if ((op == BP_PINMUX_HWLED) || (op == BP_PINMUX_PWMLED)) {
|
|
ledsrc |= 1 << lednum;
|
|
}
|
|
}
|
|
// count bits enabled for serial and add additional to byte boundary
|
|
n = 0;
|
|
for (i = 0 ; i < 32 ; i++) {
|
|
if (serial & (1 << i)) {
|
|
n++;
|
|
}
|
|
}
|
|
i = 31;
|
|
while (n % 8) {
|
|
if (serial & (1 << i)) {
|
|
printk("ERROR: could not append enough serial LEDs\n");
|
|
} else {
|
|
serial |= (1<<i);
|
|
}
|
|
i--;
|
|
n++;
|
|
}
|
|
|
|
bcm_led_set_source(serial, ledsrc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifndef _CFE_
|
|
EXPORT_SYMBOL(bcm_get_pinmux);
|
|
EXPORT_SYMBOL(bcm_set_pinmux);
|
|
EXPORT_SYMBOL(bcm_pinmux_update_optled_map);
|
|
#endif
|