[mips/broadcom] Generic platform_reset() support.
This adds support for performing platform_reset() on all supported devices, using early boot enumeration of chipc capabilities and available cores. - Added Broadcom-specific MIPS CP0 register definitions used by BCM4785-specific reset handling. - Added a bcm_platform structure for tracking chipc/pmu/cfe platform data. - Extended the BCMA EROM API to support early boot lookup of core info (including port/region mappings). - Extended platform_reset() to support PMU, PMU+AOB, and non-PMU devices. Reviewed by: mizhka Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D7539
This commit is contained in:
parent
731da97ac4
commit
2bed327ce4
@ -65,10 +65,18 @@ static int erom_skip_mport(struct bcma_erom *erom);
|
||||
static int erom_skip_sport_region(struct bcma_erom *erom);
|
||||
|
||||
static int erom_seek_next(struct bcma_erom *erom, uint8_t etype);
|
||||
static int erom_region_to_port_type(struct bcma_erom *erom,
|
||||
uint8_t region_type, bhnd_port_type *port_type);
|
||||
|
||||
#define EROM_LOG(erom, fmt, ...) \
|
||||
device_printf(erom->dev, "erom[0x%llx]: " fmt, \
|
||||
(unsigned long long) (erom->offset), ##__VA_ARGS__);
|
||||
#define EROM_LOG(erom, fmt, ...) do { \
|
||||
if (erom->dev != NULL) { \
|
||||
device_printf(erom->dev, "erom[0x%llx]: " fmt, \
|
||||
(unsigned long long) (erom->offset), ##__VA_ARGS__);\
|
||||
} else { \
|
||||
printf("erom[0x%llx]: " fmt, \
|
||||
(unsigned long long) (erom->offset), ##__VA_ARGS__);\
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Open an EROM table for reading.
|
||||
@ -82,11 +90,37 @@ static int erom_seek_next(struct bcma_erom *erom, uint8_t etype);
|
||||
* @retval non-zero if the erom table could not be opened.
|
||||
*/
|
||||
int
|
||||
bcma_erom_open(struct bcma_erom *erom, struct resource *r, bus_size_t offset)
|
||||
bcma_erom_open(struct bcma_erom *erom, struct resource *r,
|
||||
bus_size_t offset)
|
||||
{
|
||||
return (bhnd_erom_bus_space_open(erom, rman_get_device(r),
|
||||
rman_get_bustag(r), rman_get_bushandle(r), offset));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an EROM table for reading using the provided bus space tag and
|
||||
* handle.
|
||||
*
|
||||
* @param[out] erom On success, will be populated with a valid EROM
|
||||
* read state.
|
||||
* @param dev The owning device, or NULL if none.
|
||||
* @param bst EROM table bus space tag.
|
||||
* @param bsh EROM table bus space handle.
|
||||
* @param offset Offset of the EROM core from @p resource.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero if the erom table could not be opened.
|
||||
*/
|
||||
int
|
||||
bhnd_erom_bus_space_open(struct bcma_erom *erom, device_t dev,
|
||||
bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t offset)
|
||||
{
|
||||
/* Initialize the EROM reader */
|
||||
erom->dev = rman_get_device(r);
|
||||
erom->r = r;
|
||||
erom->dev = dev;
|
||||
erom->bst = bst;
|
||||
erom->bsh = bsh;
|
||||
erom->start = offset + BCMA_EROM_TABLE_START;
|
||||
erom->offset = 0;
|
||||
|
||||
@ -145,7 +179,8 @@ bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
*entry = bus_read_4(erom->r, erom->start + erom->offset);
|
||||
*entry = bus_space_read_4(erom->bst, erom->bsh,
|
||||
erom->start + erom->offset);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -299,6 +334,20 @@ bcma_erom_reset(struct bcma_erom *erom)
|
||||
erom->offset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to the next core entry.
|
||||
*
|
||||
* @param erom EROM read state.
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The end of the EROM table was reached.
|
||||
* @retval non-zero Reading or parsing failed.
|
||||
*/
|
||||
int
|
||||
bcma_erom_seek_next_core(struct bcma_erom *erom)
|
||||
{
|
||||
return (erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to the requested core entry.
|
||||
*
|
||||
@ -386,6 +435,153 @@ bcma_erom_parse_core(struct bcma_erom *erom, struct bcma_erom_core *core)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to a region record associated with @p core_index.
|
||||
*
|
||||
* @param erom EROM read state.
|
||||
* @param core_index The index of the core record to be searched.
|
||||
* @param port_type The port type to search for.
|
||||
* @param port_num The port number to search for.
|
||||
* @param region_num The region number to search for.
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The requested region was not found.
|
||||
* @retval non-zero Reading or parsing failed.
|
||||
*/
|
||||
int
|
||||
bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index,
|
||||
bhnd_port_type port_type, u_int port_num, u_int region_num)
|
||||
{
|
||||
struct bcma_erom_core core;
|
||||
uint32_t entry;
|
||||
uint8_t region_port, region_type;
|
||||
bool found;
|
||||
int error;
|
||||
|
||||
if ((error = bcma_erom_seek_core_index(erom, core_index)))
|
||||
return (error);
|
||||
|
||||
if ((error = bcma_erom_parse_core(erom, &core)))
|
||||
return (error);
|
||||
|
||||
/* Skip master ports */
|
||||
for (u_long i = 0; i < core.num_mport; i++) {
|
||||
if ((error = erom_skip_mport(erom)))
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Seek to the region block for the given port type */
|
||||
found = false;
|
||||
while (1) {
|
||||
bhnd_port_type p_type;
|
||||
uint8_t r_type;
|
||||
|
||||
if ((error = bcma_erom_peek32(erom, &entry)))
|
||||
return (error);
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, REGION))
|
||||
return (ENOENT);
|
||||
|
||||
/* Expected region type? */
|
||||
r_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
|
||||
if ((error = erom_region_to_port_type(erom, r_type, &p_type)))
|
||||
return (error);
|
||||
|
||||
if (p_type == port_type) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip to next entry */
|
||||
if ((error = erom_skip_sport_region(erom)))
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return (ENOENT);
|
||||
|
||||
/* Found the appropriate port type block; now find the region records
|
||||
* for the given port number */
|
||||
found = false;
|
||||
for (u_int i = 0; i <= port_num; i++) {
|
||||
bhnd_port_type p_type;
|
||||
|
||||
if ((error = bcma_erom_peek32(erom, &entry)))
|
||||
return (error);
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, REGION))
|
||||
return (ENOENT);
|
||||
|
||||
/* Fetch the type/port of the first region entry */
|
||||
region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
|
||||
region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
|
||||
|
||||
/* Have we found the region entries for the desired port? */
|
||||
if (i == port_num) {
|
||||
error = erom_region_to_port_type(erom, region_type,
|
||||
&p_type);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (p_type == port_type)
|
||||
found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, seek to next block of region records */
|
||||
while (1) {
|
||||
uint8_t next_type, next_port;
|
||||
|
||||
if ((error = erom_skip_sport_region(erom)))
|
||||
return (error);
|
||||
|
||||
if ((error = bcma_erom_peek32(erom, &entry)))
|
||||
return (error);
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, REGION))
|
||||
return (ENOENT);
|
||||
|
||||
next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
|
||||
next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
|
||||
|
||||
if (next_type != region_type ||
|
||||
next_port != region_port)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return (ENOENT);
|
||||
|
||||
/* Finally, search for the requested region number */
|
||||
for (u_int i = 0; i <= region_num; i++) {
|
||||
uint8_t next_port, next_type;
|
||||
|
||||
if ((error = bcma_erom_peek32(erom, &entry)))
|
||||
return (error);
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, REGION))
|
||||
return (ENOENT);
|
||||
|
||||
/* Check for the end of the region block */
|
||||
next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
|
||||
next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
|
||||
|
||||
if (next_type != region_type ||
|
||||
next_port != region_port)
|
||||
break;
|
||||
|
||||
if (i == region_num)
|
||||
return (0);
|
||||
|
||||
if ((error = erom_skip_sport_region(erom)))
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next master port descriptor from the EROM table.
|
||||
*
|
||||
@ -491,6 +687,25 @@ bcma_erom_parse_sport_region(struct bcma_erom *erom,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a bcma_erom_core record to its bhnd_core_info representation.
|
||||
*
|
||||
* @param core EROM core record to convert.
|
||||
* @param core_idx The core index of @p core.
|
||||
* @param core_unit The core unit of @p core.
|
||||
* @param[out] info The populated bhnd_core_info representation.
|
||||
*/
|
||||
void
|
||||
bcma_erom_to_core_info(const struct bcma_erom_core *core, u_int core_idx,
|
||||
int core_unit, struct bhnd_core_info *info)
|
||||
{
|
||||
info->vendor = core->vendor;
|
||||
info->device = core->device;
|
||||
info->hwrev = core->rev;
|
||||
info->core_idx = core_idx;
|
||||
info->unit = core_unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all cores descriptors from @p erom and return the array
|
||||
* in @p cores and the count in @p num_cores. The current EROM read position
|
||||
@ -545,7 +760,8 @@ bcma_erom_get_core_info(struct bcma_erom *erom,
|
||||
/* Parse all core descriptors */
|
||||
bcma_erom_reset(erom);
|
||||
for (u_int i = 0; i < count; i++) {
|
||||
struct bcma_erom_core core;
|
||||
struct bcma_erom_core core;
|
||||
int unit;
|
||||
|
||||
/* Parse the core */
|
||||
error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE);
|
||||
@ -555,20 +771,17 @@ bcma_erom_get_core_info(struct bcma_erom *erom,
|
||||
error = bcma_erom_parse_core(erom, &core);
|
||||
if (error)
|
||||
goto cleanup;
|
||||
|
||||
/* Convert to a bhnd info record */
|
||||
buffer[i].vendor = core.vendor;
|
||||
buffer[i].device = core.device;
|
||||
buffer[i].hwrev = core.rev;
|
||||
buffer[i].core_idx = i;
|
||||
buffer[i].unit = 0;
|
||||
|
||||
/* Determine the unit number */
|
||||
unit = 0;
|
||||
for (u_int j = 0; j < i; j++) {
|
||||
if (buffer[i].vendor == buffer[j].vendor &&
|
||||
buffer[i].device == buffer[j].device)
|
||||
buffer[i].unit++;
|
||||
unit++;
|
||||
}
|
||||
|
||||
/* Convert to a bhnd info record */
|
||||
bcma_erom_to_core_info(&core, i, unit, &buffer[i]);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@ -585,6 +798,33 @@ bcma_erom_get_core_info(struct bcma_erom *erom,
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map an EROM region type to its corresponding port type.
|
||||
*
|
||||
* @param region_type Region type value.
|
||||
* @param[out] port_type On success, the corresponding port type.
|
||||
*/
|
||||
static int
|
||||
erom_region_to_port_type(struct bcma_erom *erom, uint8_t region_type,
|
||||
bhnd_port_type *port_type)
|
||||
{
|
||||
switch (region_type) {
|
||||
case BCMA_EROM_REGION_TYPE_DEVICE:
|
||||
*port_type = BHND_PORT_DEVICE;
|
||||
return (0);
|
||||
case BCMA_EROM_REGION_TYPE_BRIDGE:
|
||||
*port_type = BHND_PORT_BRIDGE;
|
||||
return (0);
|
||||
case BCMA_EROM_REGION_TYPE_MWRAP:
|
||||
case BCMA_EROM_REGION_TYPE_SWRAP:
|
||||
*port_type = BHND_PORT_AGENT;
|
||||
return (0);
|
||||
default:
|
||||
EROM_LOG(erom, "unsupported region type %hhx\n",
|
||||
region_type);
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all MMIO region descriptors for the given slave port.
|
||||
@ -608,24 +848,10 @@ erom_corecfg_fill_port_regions(struct bcma_erom *erom,
|
||||
bhnd_port_type port_type;
|
||||
|
||||
error = 0;
|
||||
|
||||
|
||||
/* Determine the port type for this region type. */
|
||||
switch (region_type) {
|
||||
case BCMA_EROM_REGION_TYPE_DEVICE:
|
||||
port_type = BHND_PORT_DEVICE;
|
||||
break;
|
||||
case BCMA_EROM_REGION_TYPE_BRIDGE:
|
||||
port_type = BHND_PORT_BRIDGE;
|
||||
break;
|
||||
case BCMA_EROM_REGION_TYPE_MWRAP:
|
||||
case BCMA_EROM_REGION_TYPE_SWRAP:
|
||||
port_type = BHND_PORT_AGENT;
|
||||
break;
|
||||
default:
|
||||
EROM_LOG(erom, "unsupported region type %hhx\n",
|
||||
region_type);
|
||||
return (EINVAL);
|
||||
}
|
||||
if ((error = erom_region_to_port_type(erom, region_type, &port_type)))
|
||||
return (error);
|
||||
|
||||
/* Fetch the list to be populated */
|
||||
sports = bcma_corecfg_get_port_list(corecfg, port_type);
|
||||
|
@ -40,10 +40,11 @@
|
||||
* EROM read context.
|
||||
*/
|
||||
struct bcma_erom {
|
||||
device_t dev; /**< EROM parent device */
|
||||
struct resource *r; /**< EROM table resource. */
|
||||
bus_size_t start; /**< EROM table offset */
|
||||
bus_size_t offset; /**< current read offset */
|
||||
device_t dev; /**< EROM parent device */
|
||||
bus_space_tag_t bst; /**< EROM table bus space */
|
||||
bus_space_handle_t bsh; /**< EROM table bus handle */
|
||||
bus_size_t start; /**< EROM table offset */
|
||||
bus_size_t offset; /**< current read offset */
|
||||
};
|
||||
|
||||
/** EROM core descriptor. */
|
||||
@ -78,22 +79,34 @@ struct bcma_erom_sport_region {
|
||||
int bcma_erom_open(struct bcma_erom *erom, struct resource *r,
|
||||
bus_size_t offset);
|
||||
|
||||
int bhnd_erom_bus_space_open(struct bcma_erom *erom, device_t owner,
|
||||
bus_space_tag_t bst, bus_space_handle_t bsh,
|
||||
bus_size_t offset);
|
||||
|
||||
int bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry);
|
||||
bus_size_t bcma_erom_tell(struct bcma_erom *erom);
|
||||
void bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset);
|
||||
void bcma_erom_reset(struct bcma_erom *erom);
|
||||
|
||||
int bcma_erom_seek_next_core(struct bcma_erom *erom);
|
||||
int bcma_erom_seek_core_index(struct bcma_erom *erom,
|
||||
u_int core_index);
|
||||
int bcma_erom_parse_core(struct bcma_erom *erom,
|
||||
struct bcma_erom_core *core);
|
||||
|
||||
int bcma_erom_seek_core_sport_region(struct bcma_erom *erom,
|
||||
u_int core_index, bhnd_port_type port_type, u_int port_num,
|
||||
u_int region_num);
|
||||
|
||||
int bcma_erom_parse_mport(struct bcma_erom *erom,
|
||||
struct bcma_erom_mport *mport);
|
||||
|
||||
int bcma_erom_parse_sport_region(struct bcma_erom *erom,
|
||||
struct bcma_erom_sport_region *region);
|
||||
|
||||
void bcma_erom_to_core_info(const struct bcma_erom_core *core,
|
||||
u_int core_idx, int core_unit, struct bhnd_core_info *info);
|
||||
|
||||
int bcma_erom_get_core_info(struct bcma_erom *erom,
|
||||
struct bhnd_core_info **cores,
|
||||
u_int *num_cores);
|
||||
|
@ -535,6 +535,12 @@
|
||||
#define BHND_CHIPTYPE_UBUS 2 /**< ubus interconnect found in bcm63xx devices */
|
||||
#define BHND_CHIPTYPE_BCMA_ALT 3 /**< bcma(4) interconnect */
|
||||
|
||||
/** Evaluates to true if @p _type uses a BCMA EROM table */
|
||||
#define BHND_CHIPTYPE_HAS_EROM(_type) \
|
||||
((_type) == BHND_CHIPTYPE_BCMA || \
|
||||
(_type) == BHND_CHIPTYPE_BCMA_ALT || \
|
||||
(_type) == BHND_CHIPTYPE_UBUS)
|
||||
|
||||
/* Boardflags */
|
||||
#define BHND_BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */
|
||||
#define BHND_BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */
|
||||
|
@ -834,12 +834,16 @@ bhnd_read_chipid(device_t dev, struct resource_spec *rs,
|
||||
bus_size_t chipc_offset, struct bhnd_chipid *result)
|
||||
{
|
||||
struct resource *res;
|
||||
bhnd_addr_t enum_addr;
|
||||
uint32_t reg;
|
||||
uint8_t chip_type;
|
||||
int error, rid, rtype;
|
||||
|
||||
/* Allocate the ChipCommon window resource and fetch the chipid data */
|
||||
rid = rs->rid;
|
||||
rtype = rs->type;
|
||||
error = 0;
|
||||
|
||||
/* Allocate the ChipCommon window resource and fetch the chipid data */
|
||||
res = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE);
|
||||
if (res == NULL) {
|
||||
device_printf(dev,
|
||||
@ -849,30 +853,23 @@ bhnd_read_chipid(device_t dev, struct resource_spec *rs,
|
||||
|
||||
/* Fetch the basic chip info */
|
||||
reg = bus_read_4(res, chipc_offset + CHIPC_ID);
|
||||
*result = bhnd_parse_chipid(reg, 0x0);
|
||||
chip_type = CHIPC_GET_BITS(reg, CHIPC_ID_BUS);
|
||||
|
||||
/* Fetch the enum base address */
|
||||
error = 0;
|
||||
switch (result->chip_type) {
|
||||
case BHND_CHIPTYPE_SIBA:
|
||||
result->enum_addr = BHND_DEFAULT_CHIPC_ADDR;
|
||||
break;
|
||||
case BHND_CHIPTYPE_BCMA:
|
||||
case BHND_CHIPTYPE_BCMA_ALT:
|
||||
result->enum_addr = bus_read_4(res, chipc_offset +
|
||||
CHIPC_EROMPTR);
|
||||
break;
|
||||
case BHND_CHIPTYPE_UBUS:
|
||||
device_printf(dev, "unsupported ubus/bcm63xx chip type");
|
||||
error = ENODEV;
|
||||
goto cleanup;
|
||||
default:
|
||||
device_printf(dev, "unknown chip type %hhu\n",
|
||||
result->chip_type);
|
||||
/* Fetch the EROMPTR */
|
||||
if (BHND_CHIPTYPE_HAS_EROM(chip_type)) {
|
||||
enum_addr = bus_read_4(res, chipc_offset + CHIPC_EROMPTR);
|
||||
} else if (chip_type == BHND_CHIPTYPE_SIBA) {
|
||||
/* siba(4) uses the ChipCommon base address as the enumeration
|
||||
* address */
|
||||
enum_addr = rman_get_start(res) + chipc_offset;
|
||||
} else {
|
||||
device_printf(dev, "unknown chip type %hhu\n", chip_type);
|
||||
error = ENODEV;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*result = bhnd_parse_chipid(reg, enum_addr);
|
||||
|
||||
cleanup:
|
||||
/* Clean up */
|
||||
bus_release_resource(dev, rtype, rid, res);
|
||||
|
@ -35,6 +35,16 @@
|
||||
* the core count via the chip identification register. */
|
||||
#define CHIPC_NCORES_MIN_HWREV(hwrev) ((hwrev) == 4 || (hwrev) >= 6)
|
||||
|
||||
/** Evaluates to true if the given ChipCommon core revision supports
|
||||
* the CHIPC_CAPABILITIES_EXT register */
|
||||
#define CHIPC_HWREV_HAS_CAP_EXT(hwrev) ((hwrev) >= 35)
|
||||
|
||||
/** Evaluates to true if the chipcommon core (determined from the provided
|
||||
* @p _chipid (CHIPC_ID) register value) provides a pointer to the enumeration
|
||||
* table via CHIPC_EROMPTR */
|
||||
#define CHIPC_HAS_EROMPTR(_chipid) \
|
||||
(CHIPC_GET_BITS((_chipid), CHIPC_ID_BUS) != BHND_CHIPTYPE_SIBA)
|
||||
|
||||
#define CHIPC_GET_FLAG(_value, _flag) (((_value) & _flag) != 0)
|
||||
#define CHIPC_GET_BITS(_value, _field) \
|
||||
((_value & _field ## _MASK) >> _field ## _SHIFT)
|
||||
|
100
sys/mips/broadcom/bcm_bcma.c
Normal file
100
sys/mips/broadcom/bcm_bcma.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
#include <dev/bhnd/bcma/bcma_eromvar.h>
|
||||
|
||||
#include "bcm_machdep.h"
|
||||
|
||||
#define BCMFC_ERR(fmt, ...) printf("%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
int
|
||||
bcm_find_core_bcma(struct bhnd_chipid *chipid, bhnd_devclass_t devclass,
|
||||
int unit, struct bhnd_core_info *info, uintptr_t *addr)
|
||||
{
|
||||
struct bcma_erom erom;
|
||||
struct bcma_erom_core core;
|
||||
struct bcma_erom_sport_region region;
|
||||
bhnd_devclass_t core_class;
|
||||
int error;
|
||||
|
||||
error = bhnd_erom_bus_space_open(&erom, NULL, mips_bus_space_generic,
|
||||
(bus_space_handle_t) BCM_SOC_ADDR(chipid->enum_addr, 0), 0);
|
||||
if (error) {
|
||||
BCMFC_ERR("erom open failed: %d\n", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
for (u_long core_index = 0; core_index < ULONG_MAX; core_index++) {
|
||||
/* Fetch next core record */
|
||||
if ((error = bcma_erom_seek_next_core(&erom)))
|
||||
return (error);
|
||||
|
||||
if ((error = bcma_erom_parse_core(&erom, &core))) {
|
||||
BCMFC_ERR("core parse failed: %d\n", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Check for match */
|
||||
core_class = bhnd_find_core_class(core.vendor,
|
||||
core.device);
|
||||
if (core_class != devclass)
|
||||
continue;
|
||||
|
||||
/* Provide the basic core info */
|
||||
if (info != NULL)
|
||||
bcma_erom_to_core_info(&core, core_index, 0, info);
|
||||
|
||||
/* Provide the core's device0.0 port address */
|
||||
error = bcma_erom_seek_core_sport_region(&erom, core_index,
|
||||
BHND_PORT_DEVICE, 0, 0);
|
||||
if (error) {
|
||||
BCMFC_ERR("sport not found: %d\n", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if ((error = bcma_erom_parse_sport_region(&erom, ®ion))) {
|
||||
BCMFC_ERR("sport parse failed: %d\n", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (addr != NULL)
|
||||
*addr = region.base_addr;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return (ENOENT);
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Bruce M. Simpson.
|
||||
* Copyright (c) 2016 Michael Zhilin <mizhka@gmail.com>
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -71,6 +72,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/trap.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
#include <dev/bhnd/bhndreg.h>
|
||||
|
||||
#include <dev/bhnd/bcma/bcma_eromvar.h>
|
||||
|
||||
#include <dev/bhnd/siba/sibareg.h>
|
||||
#include <dev/bhnd/siba/sibavar.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
|
||||
#include "bcm_machdep.h"
|
||||
#include "bcm_mips_exts.h"
|
||||
#include "bcm_socinfo.h"
|
||||
|
||||
#ifdef CFE
|
||||
@ -83,8 +96,150 @@ __FBSDID("$FreeBSD$");
|
||||
#define BCM_TRACE(_fmt, ...)
|
||||
#endif
|
||||
|
||||
extern int *edata;
|
||||
extern int *end;
|
||||
static int bcm_find_core(struct bhnd_chipid *chipid,
|
||||
bhnd_devclass_t devclass, int unit,
|
||||
struct bhnd_core_info *info, uintptr_t *addr);
|
||||
static int bcm_init_platform_data(struct bcm_platform *pdata);
|
||||
|
||||
/* Allow bus-specific implementations to override bcm_find_core_(bcma|siba)
|
||||
* symbols, if included in the kernel build */
|
||||
__weak_reference(bcm_find_core_default, bcm_find_core_bcma);
|
||||
__weak_reference(bcm_find_core_default, bcm_find_core_siba);
|
||||
|
||||
extern int *edata;
|
||||
extern int *end;
|
||||
|
||||
static struct bcm_platform bcm_platform_data;
|
||||
static bool bcm_platform_data_avail = false;
|
||||
|
||||
struct bcm_platform *
|
||||
bcm_get_platform(void)
|
||||
{
|
||||
if (!bcm_platform_data_avail)
|
||||
panic("platform data not available");
|
||||
|
||||
return (&bcm_platform_data);
|
||||
}
|
||||
|
||||
/* Default (no-op) bcm_find_core() implementation. */
|
||||
int
|
||||
bcm_find_core_default(struct bhnd_chipid *chipid, bhnd_devclass_t devclass,
|
||||
int unit, struct bhnd_core_info *info, uintptr_t *addr)
|
||||
{
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search @p chipid's enumeration table for a core with @p devclass and
|
||||
* @p unit.
|
||||
*
|
||||
* @param chipid Chip identification data, including the address
|
||||
* of the enumeration table to be searched.
|
||||
* @param devclass Search for a core matching this device class.
|
||||
* @param unit The core's required unit number.
|
||||
* @param[out] info On success, will be populated with the core
|
||||
* info.
|
||||
*/
|
||||
static int
|
||||
bcm_find_core(struct bhnd_chipid *chipid, bhnd_devclass_t devclass, int unit,
|
||||
struct bhnd_core_info *info, uintptr_t *addr)
|
||||
{
|
||||
switch (chipid->chip_type) {
|
||||
case BHND_CHIPTYPE_SIBA:
|
||||
return (bcm_find_core_siba(chipid, devclass, unit, info, addr));
|
||||
break;
|
||||
default:
|
||||
if (!BHND_CHIPTYPE_HAS_EROM(chipid->chip_type)) {
|
||||
printf("%s: unsupported chip type: %d\n", __FUNCTION__,
|
||||
chipid->chip_type);
|
||||
return (ENXIO);
|
||||
}
|
||||
return (bcm_find_core_bcma(chipid, devclass, unit, info, addr));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate platform configuration data.
|
||||
*/
|
||||
static int
|
||||
bcm_init_platform_data(struct bcm_platform *pdata)
|
||||
{
|
||||
uint32_t reg;
|
||||
bhnd_addr_t enum_addr;
|
||||
long maddr;
|
||||
uint8_t chip_type;
|
||||
bool aob, pmu;
|
||||
int error;
|
||||
|
||||
/* Fetch CFE console handle (if any). Must be initialized before
|
||||
* any calls to printf/early_putc. */
|
||||
#ifdef CFE
|
||||
if ((pdata->cfe_console = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE)) < 0)
|
||||
pdata->cfe_console = -1;
|
||||
#endif
|
||||
|
||||
/* Fetch bhnd/chipc address */
|
||||
if (resource_long_value("bhnd", 0, "maddr", &maddr) == 0)
|
||||
pdata->cc_addr = (u_long)maddr;
|
||||
else
|
||||
pdata->cc_addr = BHND_DEFAULT_CHIPC_ADDR;
|
||||
|
||||
/* Read chip identifier from ChipCommon */
|
||||
reg = BCM_SOC_READ_4(pdata->cc_addr, CHIPC_ID);
|
||||
chip_type = CHIPC_GET_BITS(reg, CHIPC_ID_BUS);
|
||||
|
||||
if (BHND_CHIPTYPE_HAS_EROM(chip_type))
|
||||
enum_addr = BCM_SOC_READ_4(pdata->cc_addr, CHIPC_EROMPTR);
|
||||
else
|
||||
enum_addr = pdata->cc_addr;
|
||||
|
||||
pdata->id = bhnd_parse_chipid(reg, enum_addr);
|
||||
|
||||
/* Fetch chipc core info and capabilities */
|
||||
pdata->cc_caps = BCM_SOC_READ_4(pdata->cc_addr, CHIPC_CAPABILITIES);
|
||||
|
||||
error = bcm_find_core(&pdata->id, BHND_DEVCLASS_CC, 0, &pdata->cc_id,
|
||||
NULL);
|
||||
if (error) {
|
||||
printf("%s: error locating chipc core: %d", __FUNCTION__,
|
||||
error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (CHIPC_HWREV_HAS_CAP_EXT(pdata->cc_id.hwrev)) {
|
||||
pdata->cc_caps_ext = BCM_SOC_READ_4(pdata->cc_addr,
|
||||
CHIPC_CAPABILITIES_EXT);
|
||||
} else {
|
||||
pdata->cc_caps_ext = 0x0;
|
||||
}
|
||||
|
||||
/* Fetch PMU info */
|
||||
pmu = CHIPC_GET_FLAG(pdata->cc_caps, CHIPC_CAP_PMU);
|
||||
aob = CHIPC_GET_FLAG(pdata->cc_caps_ext, CHIPC_CAP2_AOB);
|
||||
|
||||
if (pmu && aob) {
|
||||
/* PMU block mapped to a PMU core on the Always-on-Bus (aob) */
|
||||
error = bcm_find_core(&pdata->id, BHND_DEVCLASS_PMU, 0,
|
||||
&pdata->pmu_id, &pdata->pmu_addr);
|
||||
|
||||
if (error) {
|
||||
printf("%s: error locating pmu core: %d", __FUNCTION__,
|
||||
error);
|
||||
return (error);
|
||||
}
|
||||
} else if (pmu) {
|
||||
/* PMU block mapped to chipc */
|
||||
pdata->pmu_addr = pdata->cc_addr;
|
||||
pdata->pmu_id = pdata->cc_id;
|
||||
} else {
|
||||
/* No PMU */
|
||||
pdata->pmu_addr = 0x0;
|
||||
memset(&pdata->pmu_id, 0, sizeof(pdata->pmu_id));
|
||||
}
|
||||
|
||||
bcm_platform_data_avail = true;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
platform_cpu_init()
|
||||
@ -162,23 +317,42 @@ mips_init(void)
|
||||
void
|
||||
platform_reset(void)
|
||||
{
|
||||
bool bcm4785war;
|
||||
|
||||
printf("bcm::platform_reset()\n");
|
||||
intr_disable();
|
||||
|
||||
#if defined(CFE)
|
||||
cfe_exit(0, 0);
|
||||
#else
|
||||
/* PMU watchdog reset */
|
||||
BCM_WRITE_REG32(BCM_REG_CHIPC_PMUWD_OFFS, 2); /* PMU watchdog */
|
||||
#ifdef CFE
|
||||
/* Fall back on CFE if reset requested during platform
|
||||
* data initialization */
|
||||
if (!bcm_platform_data_avail) {
|
||||
cfe_exit(0, 0);
|
||||
while (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Non-PMU reset
|
||||
* XXX: Need chipc capability flags */
|
||||
*((volatile uint8_t *)MIPS_PHYS_TO_KSEG1(SENTRY5_EXTIFADR)) = 0x80;
|
||||
#endif
|
||||
|
||||
for (;;);
|
||||
/* Handle BCM4785-specific behavior */
|
||||
bcm4785war = false;
|
||||
if (bcm_get_platform()->id.chip_id == BHND_CHIPID_BCM4785) {
|
||||
bcm4785war = true;
|
||||
|
||||
/* Switch to async mode */
|
||||
bcm_mips_wr_pllcfg3(MIPS_BCMCFG_PLLCFG3_SM);
|
||||
}
|
||||
|
||||
/* Set watchdog (PMU or ChipCommon) */
|
||||
if (bcm_get_platform()->pmu_addr != 0x0) {
|
||||
BCM_CHIPC_WRITE_4(CHIPC_PMU_WATCHDOG, 1);
|
||||
} else
|
||||
BCM_CHIPC_WRITE_4(CHIPC_WATCHDOG, 1);
|
||||
|
||||
/* BCM4785 */
|
||||
if (bcm4785war) {
|
||||
mips_sync();
|
||||
__asm __volatile("wait");
|
||||
}
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -188,6 +362,7 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
|
||||
vm_offset_t kernend;
|
||||
uint64_t platform_counter_freq;
|
||||
struct bcm_socinfo *socinfo;
|
||||
int error;
|
||||
|
||||
/* clear the BSS and SBSS segments */
|
||||
kernend = (vm_offset_t)&end;
|
||||
@ -213,36 +388,9 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
|
||||
cfe_init(a0, a2);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Probe the Broadcom on-chip PLL clock registers
|
||||
* and discover the CPU pipeline clock and bus clock
|
||||
* multipliers from this.
|
||||
* XXX: Wrong place. You have to ask the ChipCommon
|
||||
* or External Interface cores on the SiBa.
|
||||
*/
|
||||
uint32_t busmult, cpumult, refclock, clkcfg1;
|
||||
#define S5_CLKCFG1_REFCLOCK_MASK 0x0000001F
|
||||
#define S5_CLKCFG1_BUSMULT_MASK 0x000003E0
|
||||
#define S5_CLKCFG1_BUSMULT_SHIFT 5
|
||||
#define S5_CLKCFG1_CPUMULT_MASK 0xFFFFFC00
|
||||
#define S5_CLKCFG1_CPUMULT_SHIFT 10
|
||||
|
||||
counter_freq = 100000000; /* XXX */
|
||||
|
||||
clkcfg1 = s5_rd_clkcfg1();
|
||||
printf("clkcfg1 = 0x%08x\n", clkcfg1);
|
||||
|
||||
refclock = clkcfg1 & 0x1F;
|
||||
busmult = ((clkcfg1 & 0x000003E0) >> 5) + 1;
|
||||
cpumult = ((clkcfg1 & 0xFFFFFC00) >> 10) + 1;
|
||||
|
||||
printf("refclock = %u\n", refclock);
|
||||
printf("busmult = %u\n", busmult);
|
||||
printf("cpumult = %u\n", cpumult);
|
||||
|
||||
counter_freq = cpumult * refclock;
|
||||
#endif
|
||||
/* Init BCM platform data */
|
||||
if ((error = bcm_init_platform_data(&bcm_platform_data)))
|
||||
panic("bcm_init_platform_data() failed: %d", error);
|
||||
|
||||
socinfo = bcm_get_socinfo();
|
||||
platform_counter_freq = socinfo->cpurate * 1000 * 1000; /* BCM4718 is 480MHz */
|
||||
@ -267,20 +415,20 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
|
||||
static void
|
||||
bcm_cfe_eputc(int c)
|
||||
{
|
||||
static int fd = -1;
|
||||
unsigned char ch;
|
||||
int handle;
|
||||
|
||||
ch = (unsigned char) c;
|
||||
|
||||
if (fd == -1) {
|
||||
if ((fd = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE)) < 0)
|
||||
return;
|
||||
}
|
||||
/* bcm_get_platform() cannot be used here, as we may be called
|
||||
* from bcm_init_platform_data(). */
|
||||
if ((handle = bcm_platform_data.cfe_console) < 0)
|
||||
return;
|
||||
|
||||
if (ch == '\n')
|
||||
early_putc('\r');
|
||||
|
||||
while ((cfe_write(fd, &ch, 1)) == 0)
|
||||
while ((cfe_write(handle, &ch, 1)) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
93
sys/mips/broadcom/bcm_machdep.h
Normal file
93
sys/mips/broadcom/bcm_machdep.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_BROADCOM_BCM_MACHDEP_H_
|
||||
#define _MIPS_BROADCOM_BCM_MACHDEP_H_
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/cpuregs.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
struct bcm_platform {
|
||||
struct bhnd_chipid id; /**< chip id */
|
||||
struct bhnd_core_info cc_id; /**< chipc core info */
|
||||
uintptr_t cc_addr; /**< chipc core phys address */
|
||||
uint32_t cc_caps; /**< chipc capabilities */
|
||||
uint32_t cc_caps_ext; /**< chipc extended capabilies */
|
||||
|
||||
/* On non-AOB devices, the PMU register block is mapped to chipc;
|
||||
* the pmu_id and pmu_addr values will be copied from cc_id
|
||||
* and cc_addr. */
|
||||
struct bhnd_core_info pmu_id; /**< PMU core info */
|
||||
uintptr_t pmu_addr; /**< PMU core phys address. */
|
||||
|
||||
#ifdef CFE
|
||||
int cfe_console; /**< Console handle, or -1 */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef int (bcm_bus_find_core)(struct bhnd_chipid *chipid,
|
||||
bhnd_devclass_t devclass, int unit, struct bhnd_core_info *info,
|
||||
uintptr_t *addr);
|
||||
|
||||
struct bcm_platform *bcm_get_platform(void);
|
||||
|
||||
bcm_bus_find_core bcm_find_core_default;
|
||||
bcm_bus_find_core bcm_find_core_bcma;
|
||||
bcm_bus_find_core bcm_find_core_siba;
|
||||
|
||||
#define BCM_SOC_ADDR(_addr, _offset) \
|
||||
MIPS_PHYS_TO_KSEG1((_addr) + (_offset))
|
||||
|
||||
#define BCM_SOC_READ_4(_addr, _offset) \
|
||||
readl(BCM_SOC_ADDR((_addr), (_offset)))
|
||||
#define BCM_SOC_WRITE_4(_addr, _reg, _val) \
|
||||
writel(BCM_SOC_ADDR((_addr), (_offset)), (_val))
|
||||
|
||||
#define BCM_CORE_ADDR(_name, _reg) \
|
||||
BCM_SOC_ADDR(bcm_get_platform()->_name, (_reg))
|
||||
|
||||
#define BCM_CORE_READ_4(_name, _reg) \
|
||||
readl(BCM_CORE_ADDR(_name, (_reg)))
|
||||
#define BCM_CORE_WRITE_4(_name, _reg, _val) \
|
||||
writel(BCM_CORE_ADDR(_name, (_reg)), (_val))
|
||||
|
||||
#define BCM_CHIPC_READ_4(_reg) BCM_CORE_READ_4(cc_addr, (_reg))
|
||||
#define BCM_CHIPC_WRITE_4(_reg, _val) \
|
||||
BCM_CORE_WRITE_4(cc_addr, (_reg), (_val))
|
||||
|
||||
#define BCM_PMU_READ_4(_reg) BCM_CORE_READ_4(pmu_addr, (_reg))
|
||||
#define BCM_PMU_WRITE_4(_reg, _val) \
|
||||
BCM_CORE_WRITE_4(pmu_addr, (_reg), (_val))
|
||||
|
||||
#endif /* _MIPS_BROADCOM_BCM_MACHDEP_H_ */
|
190
sys/mips/broadcom/bcm_mips_exts.h
Normal file
190
sys/mips/broadcom/bcm_mips_exts.h
Normal file
@ -0,0 +1,190 @@
|
||||
/*-
|
||||
* Copyright 2000,2001,2002,2003 Broadcom Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is derived from the sbmips32.h header distributed
|
||||
* by Broadcom with the CFE 1.4.2 sources.
|
||||
*
|
||||
* This software is furnished under license and may be used and
|
||||
* copied only in accordance with the following terms and
|
||||
* conditions. Subject to these conditions, you may download,
|
||||
* copy, install, use, modify and distribute modified or unmodified
|
||||
* copies of this software in source and/or binary form. No title
|
||||
* or ownership is transferred hereby.
|
||||
*
|
||||
* 1) Any source code used, modified or distributed must reproduce
|
||||
* and retain this copyright notice and list of conditions
|
||||
* as they appear in the source file.
|
||||
*
|
||||
* 2) No right is granted to use any trade name, trademark, or
|
||||
* logo of Broadcom Corporation. The "Broadcom Corporation"
|
||||
* name may not be used to endorse or promote products derived
|
||||
* from this software without the prior written permission of
|
||||
* Broadcom Corporation.
|
||||
*
|
||||
* 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
|
||||
* PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
||||
/* *********************************************************************
|
||||
* Broadcom Common Firmware Environment (CFE)
|
||||
*
|
||||
* MIPS32 CPU definitions File: sbmips32.h
|
||||
*
|
||||
* This module contains constants and macros specific to the
|
||||
* Broadcom MIPS32 core. In addition to generic MIPS32, it
|
||||
* includes definitions for the MIP32-01 and MIPS3302 OCP cores
|
||||
* for the Silicon Backplane.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef _MIPS_BROADCOM_BCM_MIPS_EXTS_H_
|
||||
#define _MIPS_BROADCOM_BCM_MIPS_EXTS_H_
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
|
||||
/*
|
||||
* The following Broadcom Custom CP0 Registers appear in the Broadcom
|
||||
* BMIPS330x MIPS32 core.
|
||||
*/
|
||||
|
||||
#define MIPS_COP_0_BCMCFG 22
|
||||
|
||||
/*
|
||||
* Custom CP0 Accessors
|
||||
*/
|
||||
|
||||
#define BCM_MIPS_RW32_COP0_SEL(n,r,s) \
|
||||
static __inline uint32_t \
|
||||
bcm_mips_rd_ ## n(void) \
|
||||
{ \
|
||||
int v0; \
|
||||
__asm __volatile ("mfc0 %[v0], $"__XSTRING(r)", "__XSTRING(s)";" \
|
||||
: [v0] "=&r"(v0)); \
|
||||
mips_barrier(); \
|
||||
return (v0); \
|
||||
} \
|
||||
static __inline void \
|
||||
bcm_mips_wr_ ## n(uint32_t a0) \
|
||||
{ \
|
||||
__asm __volatile ("mtc0 %[a0], $"__XSTRING(r)", "__XSTRING(s)";" \
|
||||
__XSTRING(COP0_SYNC)";" \
|
||||
"nop;" \
|
||||
"nop;" \
|
||||
: \
|
||||
: [a0] "r"(a0)); \
|
||||
mips_barrier(); \
|
||||
} struct __hack
|
||||
|
||||
BCM_MIPS_RW32_COP0_SEL(pllcfg1, MIPS_COP_0_CONFIG, 1);
|
||||
BCM_MIPS_RW32_COP0_SEL(pllcfg2, MIPS_COP_0_CONFIG, 2);
|
||||
BCM_MIPS_RW32_COP0_SEL(clksync, MIPS_COP_0_CONFIG, 3);
|
||||
BCM_MIPS_RW32_COP0_SEL(pllcfg3, MIPS_COP_0_CONFIG, 4);
|
||||
BCM_MIPS_RW32_COP0_SEL(rstcfg, MIPS_COP_0_CONFIG, 5);
|
||||
|
||||
/*
|
||||
* Broadcom PLLConfig1 Register (22, select 1)
|
||||
*/
|
||||
|
||||
/* SoftMIPSPLLCfg */
|
||||
#define MIPS_BCMCFG_PLLCFG1_MC_SHIFT 10
|
||||
#define MIPS_BCMCFG_PLLCFG1_MC_MASK 0xFFFFFC00
|
||||
|
||||
/* SoftISBPLLCfg */
|
||||
#define MIPS_BCMCFG_PLLCFG1_BC_SHIFT 5
|
||||
#define MIPS_BCMCFG_PLLCFG1_BC_MASK 0x000003E0
|
||||
|
||||
/* SoftRefPLLCfg */
|
||||
#define MIPS_BCMCFG_PLLCFG1_PC_SHIFT 0
|
||||
#define MIPS_BCMCFG_PLLCFG1_PC_MASK 0x0000001F
|
||||
|
||||
/*
|
||||
* Broadcom PLLConfig2 Register (22, select 2)
|
||||
*/
|
||||
|
||||
/* Soft1to1ClkRatio */
|
||||
#define MIPS_BCMCFG_PLLCFG2_CR (1<<23)
|
||||
|
||||
/* SoftUSBxPLLCfg */
|
||||
#define MIPS_BCMCFG_PLLCFG2_UC_SHIFT 15
|
||||
#define MIPS_BCMCFG_PLLCFG2_UC_MASK 0x007F8000
|
||||
|
||||
/* SoftIDExPLLCfg */
|
||||
#define MIPS_BCMCFG_PLLCFG2_IC_SHIFT 7
|
||||
#define MIPS_BCMCFG_PLLCFG2_IC_MASK 0x00007F80
|
||||
|
||||
#define MIPS_BCMCFG_PLLCFG2_BE (1<<6) /* ISBxSoftCfgEnable */
|
||||
#define MIPS_BCMCFG_PLLCFG2_UE (1<<5) /* USBxSoftCfgEnable */
|
||||
#define MIPS_BCMCFG_PLLCFG2_IE (1<<4) /* IDExSoftCfgEnable */
|
||||
#define MIPS_BCMCFG_PLLCFG2_CA (1<<3) /* CfgActive */
|
||||
#define MIPS_BCMCFG_PLLCFG2_CF (1<<2) /* RefSoftCfgEnable */
|
||||
#define MIPS_BCMCFG_PLLCFG2_CI (1<<1) /* ISBSoftCfgEnable */
|
||||
#define MIPS_BCMCFG_PLLCFG2_CC (1<<0) /* MIPSSoftCfgEnable */
|
||||
|
||||
/*
|
||||
* Broadcom ClkSync Register (22, select 3)
|
||||
*/
|
||||
/* SoftClkCfgHigh */
|
||||
#define MIPS_BCMCFG_CLKSYNC_CH_SHIFT 16
|
||||
#define MIPS_BCMCFG_CLKSYNC_CH_MASK 0xFFFF0000
|
||||
|
||||
/* SoftClkCfgLow */
|
||||
#define MIPS_BCMCFG_CLKSYNC_CL_SHIFT 0
|
||||
#define MIPS_BCMCFG_CLKSYNC_CL_MASK 0x0000FFFF
|
||||
|
||||
/*
|
||||
* Broadcom ISBxPLLConfig3 Register (22, select 4)
|
||||
*/
|
||||
|
||||
/* AsyncClkRatio */
|
||||
#define MIPS_BCMCFG_PLLCFG3_AR_SHIFT 23
|
||||
#define MIPS_BCMCFG_PLLCFG3_AR_MASK 0x01800000
|
||||
|
||||
#define MIPS_BCMCFG_PLLCFG3_SM (1<<22) /* SyncMode */
|
||||
|
||||
/* SoftISBxPLLCfg */
|
||||
#define MIPS_BCMCFG_PLLCFG3_IC_SHIFT 0
|
||||
#define MIPS_BCMCFG_PLLCFG3_IC_MASK 0x003FFFFF
|
||||
|
||||
/*
|
||||
* Broadcom BRCMRstConfig Register (22, select 5)
|
||||
*/
|
||||
|
||||
#define MIPS_BCMCFG_RSTCFG_SR (1<<18) /* SSMR */
|
||||
#define MIPS_BCMCFG_RSTCFG_DT (1<<16) /* BHTD */
|
||||
|
||||
/* RStSt */
|
||||
#define MIPS_BCMCFG_RSTCFG_RS_SHIFT 8
|
||||
#define MIPS_BCMCFG_RSTCFG_RS_MASK 0x00001F00
|
||||
#define MIPS_BCMCFG_RST_OTHER 0x00
|
||||
#define MIPS_BCMCFG_RST_SH 0x01
|
||||
#define MIPS_BCMCFG_RST_SS 0x02
|
||||
#define MIPS_BCMCFG_RST_EJTAG 0x04
|
||||
#define MIPS_BCMCFG_RST_WDOG 0x08
|
||||
#define MIPS_BCMCFG_RST_CRC 0x10
|
||||
|
||||
#define MIPS_BCMCFG_RSTCFG_CR (1<<7) /* RStCr */
|
||||
|
||||
/* WBMD */
|
||||
#define MIPS_BCMCFG_RSTCFG_WD_SHIFT 3
|
||||
#define MIPS_BCMCFG_RSTCFG_WD_MASK 0x00000078
|
||||
|
||||
#define MIPS_BCMCFG_RSTCFG_SS (1<<2) /* SSR */
|
||||
#define MIPS_BCMCFG_RSTCFG_SH (1<<1) /* SHR */
|
||||
#define MIPS_BCMCFG_RSTCFG_BR (1<<0) /* BdR */
|
||||
|
||||
#endif /* _MIPS_BROADCOM_BCM_MIPS_EXTS_H_ */
|
64
sys/mips/broadcom/bcm_siba.c
Normal file
64
sys/mips/broadcom/bcm_siba.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
#include <dev/bhnd/bhndreg.h>
|
||||
|
||||
#include <dev/bhnd/siba/sibareg.h>
|
||||
#include <dev/bhnd/siba/sibavar.h>
|
||||
|
||||
#include "bcm_machdep.h"
|
||||
|
||||
int
|
||||
bcm_find_core_siba(struct bhnd_chipid *chipid, bhnd_devclass_t devclass,
|
||||
int unit, struct bhnd_core_info *info, uintptr_t *addr)
|
||||
{
|
||||
struct siba_core_id scid;
|
||||
uintptr_t cc_addr;
|
||||
uint32_t idhigh, idlow;
|
||||
|
||||
/* No other cores are required during early boot on siba(4) devices */
|
||||
if (devclass != BHND_DEVCLASS_CC || unit != 0)
|
||||
return (ENOENT);
|
||||
|
||||
cc_addr = chipid->enum_addr;
|
||||
idhigh = BCM_SOC_READ_4(cc_addr, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
|
||||
idlow = BCM_SOC_READ_4(cc_addr, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
|
||||
|
||||
scid = siba_parse_core_id(idhigh, idlow, 0, 0);
|
||||
|
||||
if (info != NULL)
|
||||
*info = scid.core_info;
|
||||
|
||||
if (addr != NULL)
|
||||
*addr = cc_addr;
|
||||
|
||||
return (0);
|
||||
}
|
@ -29,6 +29,10 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
|
||||
#include "bcm_machdep.h"
|
||||
#include "bcm_socinfo.h"
|
||||
|
||||
/* found on https://wireless.wiki.kernel.org/en/users/drivers/b43/soc */
|
||||
@ -85,7 +89,7 @@ bcm_get_socinfo(void)
|
||||
* --------------------------------------------------------------
|
||||
*/
|
||||
|
||||
socid = BCM_READ_REG32(BCM_REG_CHIPC_ID) & 0x00FFFFFF;
|
||||
socid = BCM_CHIPC_READ_4(CHIPC_ID) & 0x00FFFFFF;
|
||||
socinfo = bcm_get_socinfo_by_socid(socid);
|
||||
return (socinfo != NULL) ? socinfo : &BCM_DEFAULT_SOCINFO;
|
||||
}
|
||||
|
@ -44,17 +44,4 @@ struct bcm_socinfo {
|
||||
struct bcm_socinfo* bcm_get_socinfo_by_socid(uint32_t key);
|
||||
struct bcm_socinfo* bcm_get_socinfo(void);
|
||||
|
||||
#define BCM_SOCADDR 0x18000000
|
||||
#define BCM_REG_CHIPC_ID 0x0
|
||||
#define BCM_REG_CHIPC_UART 0x300
|
||||
#define BCM_REG_CHIPC_PMUWD_OFFS 0x634
|
||||
#define BCM_SOCREG(reg) \
|
||||
MIPS_PHYS_TO_KSEG1((BCM_SOCADDR + (reg)))
|
||||
#define BCM_READ_REG32(reg) \
|
||||
*((volatile uint32_t *)BCM_SOCREG(reg))
|
||||
#define BCM_WRITE_REG32(reg, value) \
|
||||
do { \
|
||||
writel((void*)BCM_SOCREG((reg)),value); \
|
||||
} while (0);
|
||||
|
||||
#endif /* _MIPS_BROADCOM_BCM_SOCINFO_H_ */
|
||||
|
@ -4,7 +4,9 @@
|
||||
# for USB 1.1 OHCI, Ethernet and IPSEC cores
|
||||
# which are believed to be devices we have drivers for
|
||||
# which just need to be tweaked for attachment to an BHND system bus.
|
||||
mips/broadcom/bcm_bcma.c optional bcma_nexus bcma
|
||||
mips/broadcom/bcm_machdep.c standard
|
||||
mips/broadcom/bcm_siba.c optional siba_nexus siba
|
||||
mips/mips/tick.c standard
|
||||
mips/mips/mips_pic.c standard
|
||||
kern/subr_intr.c standard
|
||||
|
@ -45,14 +45,15 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/uart/uart_bus.h>
|
||||
#include <dev/uart/uart_cpu.h>
|
||||
|
||||
#include "bcm_socinfo.h"
|
||||
|
||||
#ifdef CFE
|
||||
#include <dev/cfe/cfe_api.h>
|
||||
#include <dev/cfe/cfe_ioctl.h>
|
||||
#include <dev/cfe/cfe_error.h>
|
||||
#endif
|
||||
|
||||
#include "bcm_machdep.h"
|
||||
#include "bcm_socinfo.h"
|
||||
|
||||
bus_space_tag_t uart_bus_space_io;
|
||||
bus_space_tag_t uart_bus_space_mem;
|
||||
|
||||
@ -78,7 +79,8 @@ uart_cpu_init(struct uart_devinfo *di, u_int uart, int baudrate)
|
||||
di->ops = uart_getops(chipc_uart_class);
|
||||
di->bas.chan = 0;
|
||||
di->bas.bst = uart_bus_space_mem;
|
||||
di->bas.bsh = (bus_space_handle_t) BCM_SOCREG(CHIPC_UART(uart));
|
||||
di->bas.bsh = (bus_space_handle_t) BCM_CORE_ADDR(cc_addr,
|
||||
CHIPC_UART(uart));
|
||||
di->bas.regshft = 0;
|
||||
di->bas.rclk = socinfo->uartrate; /* in Hz */
|
||||
di->baudrate = baudrate;
|
||||
@ -112,7 +114,7 @@ uart_getenv_cfe(int devtype, struct uart_devinfo *di)
|
||||
return (ENXIO);
|
||||
|
||||
/* Fetch device handle */
|
||||
fd = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
|
||||
fd = bcm_get_platform()->cfe_console;
|
||||
if (fd < 0)
|
||||
return (ENXIO);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user