blob: ac6444cf4c15c8912bce321539790be598f94dfc [file] [log] [blame]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/
/**
* @brief Microchip USB3503 USB 2.0 hub controller
* @see http://www.microchip.com/wwwproducts/en/USB3503
*/
#include <usb/drivers/usb3503_hub.h>
#include "../../../services.h"
#define REG_VIDL 0x00
#define REG_VIDM 0x01
#define REG_PIDL 0x02
#define REG_PIDM 0x03
#define REG_DIDL 0x04
#define REG_DIDM 0x05
#define REG_CFG1 0x06
#define REG_CFG2 0x07
#define REG_CFG3 0x08
#define REG_NRD 0x09
#define REG_PDS 0x0A
#define REG_PDB 0x0B
#define REG_MAXPS 0x0C
#define REG_MAXPB 0x0D
#define REG_HCMCS 0x0E
#define REG_HCMCB 0x0F
#define REG_PWRT 0x10
#define REG_LANG_ID_H 0x11
#define REG_LANG_ID_L 0x12
#define REG_MFR_STR_LEN 0x13
#define REG_PRD_STR_LEN 0x14
#define REG_SER_STR_LEN 0x15
#define REG_MFR_STR 0x16
#define REG_PROD_STR 0x54
#define REG_SER_STR 0x92
#define REG_BC_EN 0xD0
#define REG_PRTPWR 0xE5
#define REG_OCS 0xE6
#define REG_SP_ILOCK 0xE7
#define REG_INT_STATUS 0xE8
#define REG_INT_MASK 0xE9
#define REG_CFGP 0xEE
#define REG_VSNSUP3 0xF4
#define REG_VSNS21 0xF5
#define REG_BSTUP3 0xF6
#define REG_BST21 0xF8
#define REG_PRTSP 0xFA
#define REG_PRTR12 0xFB
#define REG_PRTR34 0xFC
#define REG_STCD 0xFF
static int read_reg(usb3503_t *hub, int addr)
{
int count;
char data;
count = i2c_kvslave_read(&hub->kvslave, addr, &data, 1);
if (count != 1) {
return -1;
} else {
return data;
}
}
static int write_reg(usb3503_t *hub, int addr, int data)
{
int count;
char cdata;
cdata = data;
count = i2c_kvslave_write(&hub->kvslave, addr, &cdata, 1);
if (count != 1) {
return -1;
} else {
return 0;
}
}
int
usb3503_init(i2c_bus_t *i2c_bus, gpio_sys_t *gpio_sys, gpio_id_t o_nreset,
gpio_id_t o_hubconnect, gpio_id_t i_nint, usb3503_t *hub)
{
if (i2c_slave_init
(i2c_bus, USB3503_I2C_ADDR, I2C_SLAVE_ADDR_7BIT, I2C_SLAVE_SPEED_FAST, 0, &hub->i2c_slave)) {
ZF_LOGE("Failed to intialize slave handle.");
return -1;
}
if (i2c_kvslave_init(&hub->i2c_slave, BIG8, BIG8, &hub->kvslave)) {
ZF_LOGE("Failed to initialize lib KV-Slave instance handle.");
return -1;
}
if (gpio_new(gpio_sys, o_nreset, GPIO_DIR_OUT, &hub->o_nreset)) {
return -1;
}
if (gpio_new(gpio_sys, o_hubconnect, GPIO_DIR_OUT, &hub->o_hubconnect)) {
return -1;
}
if (gpio_new(gpio_sys, i_nint, GPIO_DIR_OUT, &hub->i_nint)) {
return -1;
}
/* Turn off the HUB */
gpio_clr(&hub->o_nreset);
gpio_clr(&hub->o_hubconnect);
/* Select Primary or Secondary reference clock
* Primary reference clock freq (NINT high during init)
* SEL -> FREQ
* 00 -> 38.4 MHz
* 01 -> 26.0 MHz
* 10 -> 19.2 MHz
* 11 -> 12.0 MHz
*
* Secondary reference clock freq (NINT low during init)
* SEL -> FREQ
* 00 -> 24.0 MHz
* 01 -> 27.0 MHz
* 10 -> 25.0 MHz
* 11 -> 50.0 MHz
*
* Known platforms:
* Odroid - SEL = 00
*/
gpio_clr(&hub->i_nint);
/* TODO set clock frequency */
/* Start the init process */
gpio_set(&hub->o_nreset);
return 0;
}
void usb3503_reset(usb3503_t *hub)
{
write_reg(hub, REG_STCD, BIT(1));
}
void usb3503_hard_reset(usb3503_t *hub)
{
gpio_clr(&hub->o_nreset);
ps_udelay(100);
gpio_set(&hub->o_nreset);
}
void usb3503_connect(usb3503_t *hub)
{
gpio_set(&hub->o_hubconnect);
}
void usb3503_disconnect(usb3503_t *hub)
{
gpio_clr(&hub->o_hubconnect);
}
void usb3503_handle_irq(usb3503_t *hub)
{
uint8_t status, mask;
status = read_reg(hub, REG_INT_STATUS);
mask = read_reg(hub, REG_INT_MASK);
printf("HUB IRQ status: 0x%02x/0x%02x\n", status, mask);
}